Reputation: 2538
All,
Having some issues with a test much like what follows:
it "does something" do
controller.should_receive(:some_method).once
expect {
post :create, some_params_hash, some_session_hash
}.to change(Something, :count).by(1)
end
Controller on the rails side - rough example:
class SomethingsController
before_filter :some_method
def create
respond_with Something.create params[:something]
end
def some_method
puts 'some_method'
end
end
This is all well and good and works just fine if I remove the controller.should_receive expectation. If I leave the expectation in place - the test fails.
What's strange is it isn't failing on an unsatisfied expectation - it actually seems to meet the should_receive(:some_method) expectation - it's just that the record create and subsequent change evaluation fail.
So - question:
Is this the proper way to specify expectations on the controller that is invoked as part of this test??
Thanks for any help!
Upvotes: 1
Views: 1522
Reputation: 15772
A common rspec error is thinking that a method expectation like the one set up by your should_receive
simply monitors the application to make sure certain things happen. But actually it inserts itself into the flow and replaces the method entirely.
So your controller's some_method
will be replaced by one that does nothing but return nil. And a before filter that returns nil will stop all processing. Your action is never called.
Change your expectation to this:
controller.should_receive(:some_method).once.and_return true
Also note that your example is testing two things -- it's making sure your action calls some_method
and it's making sure the number of persisted Somethings increases by one. That's fine, but if you really only intended to check the latter, you could use a stub instead of an expectation, which is a little more compact:
controller.stub some_method: true
UPDATE: I should add that in recent versions of Rails, the return value of a controller filter is ignored. (The filter can prevent the action from executing just by rendering something.) However, the principle of rspec's should_receive
replacing your method is still true and generally applicable.
Upvotes: 1