3

The most direct attempt is to do

@controller.stubs(:send_file)

But that results in an output error like

ActionView::MissingTemplate: Missing template ...

So how do I stub away the send_file method from 2.3.x series.

The question is basically the same question that was asked on ruby-forum february 2009, which was never really answered.

Jarl

Machavity
  • 30,841
  • 27
  • 92
  • 100
Jarl
  • 2,831
  • 4
  • 24
  • 31
  • Why do you want to stub send_file method? Instead can you just stub the file generation logic? – Arun Kumar Arjunan Aug 17 '11 at 14:22
  • I am not sure what you mean, Arun. I have updated my question to be more specific on what I mean. – Jarl Aug 22 '11 at 08:05
  • Can you please tell us why do you want to stub the send_file method? – Arun Kumar Arjunan Aug 22 '11 at 09:37
  • I would like to stub away send_file, because I am writing a test that cares only about other behaviour of the controller, so the test shall be completely ignorant the send_file call. – Jarl Aug 22 '11 at 17:45
  • I would rather not stub the send_file method because it is equivalent to stubbing the render calls. Can you please post us the code. incase you would still like to stub them? – Arun Kumar Arjunan Aug 22 '11 at 17:52

3 Answers3

2

With Rails 4 (and maybe earlier)[1], the ImplicitRender handles this, and it checks against "performed?".

So, if you want to stub it out, stubbing the "performed?" should suffice:

subject.stubs(:performed?).returns(true)
subject.expects(:send_file).
  with(image, disposition: "inline")

The implementation of performed is not that hard either:

performed?
  response_body || (response && response.committed?)
end

So, in cases where you don't want, or cannot, stub performed simply ensure the response_body is not nil.


[1] With 5+ this has been moved into BasicImplicitRender.

berkes
  • 26,996
  • 27
  • 115
  • 206
0

I've had to fight with this as well. As far as I can tell, the best solution for me has been:

(controller)

def some_action
  send_file(some_action_filename)
end

private

def some_action_filename
  "/public/something.tgz"
end

(test)

test "some_action" do
  filename = Rails.root.join("tmp/testfile.tgz")
  assert FileUtils.touch filename  
  @controller.expects(:some_action_filename).at_least_once().returns(filename)
  post :some_action
end

I'm not a fan of altering your code to allow you to test, but I am less of a fan of spending hours and hours to find the right solution for a fairly trivial issue :)

Billy
  • 11
  • 1
0

Missing template errors probably points to the fact that send_file is now not doing anything (because of the stub) so Rails will try to go down the rendering chain and try to display the template.

You've effectively disabled the send_file call now, so you will need to change your stub to actually sends something Rails can interpret and think the request is handled because the file is served, in which case no template will need to be rendered anymore.

Bitterzoet
  • 2,752
  • 20
  • 14
  • Yes, I understand, but how do cheat the controller? See also [Ruby forum 2009](http://www.ruby-forum.com/topic/179408) – Jarl Aug 22 '11 at 17:50