Is there any way in a controller spec to 'reset' the instance variable space before each get if we have to do multiple gets in the same spec context?
I understand the one-assertion-per-test guideline. However, for one of our sets of tests, it runs about 3x faster if we don't do a separate (lengthy) before(:each) setup before each get and if we run a sequence of get/asserts together in a single context.
However, it seems that (unlike when controller methods are invoked via browser) if you do two consecutive get's with rspec, instance variables are not cleared with each get, so data crossover is possible.
Here's a failing test, showing that a variable set in 'vartest1' is still present when another controller method 'vartest2' is run:
Controller methods:
def vartest1
@this_var = "foo"
render :text => @this_var
end
def vartest2
render :text => @this_var # should be EMPTY!
end
Rspec controller spec:
describe "instance variable crossover example", :focus => true do
describe "THIS PASSES put each get in separate contexts" do
it "vartest1 outputs foo" do
get "vartest1"
response.body.should include("foo")
end
it "vartest2 does NOT output foo" do
get "vartest2"
response.body.should_not include("foo")
end
end
describe "THIS FAILS put both gets in SAME context" do
it "should not crossover controller instance varables" do
get "vartest1"
response.body.should include("foo")
get "vartest2"
response.body.should_not include("foo") # THIS FAILS
end
end
end
Rspec results:
instance variable crossover example
THIS PASSES put each get in separate contexts
vartest1 outputs foo
vartest2 does NOT output foo
THIS FAILS put both gets in SAME context
should not crossover controller instance varables (FAILED - 1)
What's happening in the failing test is that when rspec does get 'vartest1'
the controller method set an instance variable to 'foo', and when rspec does get 'vartest2'
the instance variable (which should be nil) is still set, so the test fails.
Controller specs are unit tests. Like all unit tests, they should test methods in isolation. For controllers, this means each action needs its own specs(s). Performing multiple requests in a controller spec is not likely to get you anywhere.
You might consider using a request spec, or Cucumber. Depending on your environment, this might get you better results, since the setup would only need to happen once per example. You could then do multiple gets
(or visits
).
Another possibility is to use mocks/stubs for your controller specs. This can improve performance significantly, at the price of doing additional setup. The RSpec scaffold examples for controller specs are a good starting point for this approach.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With