views:

129

answers:

2

How would one test that when an action in controller is being accessed, that controller's before_filter will be executed?

The before_filter is tested in separate example group so that there's no need to duplicate the tests for all actions that depend on the before_filter.

If I have

controller.should_receive(:my_before_filter)

in my example, it works fine. However, having the above expectation seems to cause that the logic in my_before_filter is not being executed (it should assign an instance variable).

How to overcome this restriction or to mock behaviour of my_before_filter (it sets instance variable on controller)? Or is there some better way to do this?


As it's now clear I was doing it all wrong, I'd still like to know how one could mock the behaviour of before_filter that sets an instance variable. Surely it must be a possible to do this in a controller spec?

+1  A: 

RSpec's should_receive implies that you are expecting to receive the method, but as a mock method, so it does not actually call the real method, which is "my_before_filter" in this case.

http://axonflux.com/rspecs-shouldreceive-doesnt-ac

If my_before_filter is already tested in a separate test, as you say, you should not really care that the real one is being called.

So you should test the actual functionality in one test, and test that it is being called in another, as you are already doing.

Incidentally, if you need it to return a value, you can see "Return Values" on the following page.

http://rspec.info/documentation/mocks/message_expectations.html

Kyle Heironimus
Thank you for your response.However, the problem is, I need some way to at least mock the behavior of my_before_filter. Returning values from before_filter isn't very beneficial as the only return value that has any meaning is "false" and it halts the execution of the chain.What I actually want to do is for my_before_filter to set an instance variable on controller. I have tried to mock it without success.How should I continue the controller.should_receive(:my_before_filter) line so that it assigns a instance variable before I use get :action_name in the example?
mnylen
+1  A: 

Testing the filter is looking too closely at the implementation, IMO. You want to ensure that the instance variable assignment is happening, not whether it takes place within a filter or within an action -- test the outcome, not the implementation.

zetetic
You are saying basically that as the filter is used in a number of actions inside the controller, I should duplicate the tests I have created for assigning the instance variable for each of the actions that depend on it?
mnylen
It's a tradeoff. True, you might have to duplicate some tests, but they will be less likely to break if you refactor the implementation. You can reduce the duplication by using shared example groups.Also you might end up with more test code by testing the filter separately -- you'd have to test that the filter is called for the right actions (and not for the wrong ones), and that the instance variable assignment occurs where it's supposed to.
zetetic
Thank's. I hadn't heard of shared example groups, but I'll definitely see if they're up to the task. :)
mnylen