I'm trying to make sense of the tests in an inherited app, and I need some help.
There are lots of spec groups like this one (view spec):
let(:job_post) { FactoryGirl.create(:job_post) }
# ...
before do
expect(view).to receive(:job_post).at_least(:once).and_return(job_post)
end
it "should render without error" do
render
end
... with job_post
being an helper method defined on the controller. (yes, they could have used @instance variables, and I'm in the process of refactoring it).
Now, in my opinion using an expect
inside a before
block is wrong. Let's forget about that for a second.
Normally the test above is green.
However, if I remove the expect
line, the test fails. It appears that in this case expect
is stubbing the method on the view. In fact, replacing expect
with allow
seems to have exactly the same effect.
I think that what's going on is that normally – when run with a server – the view will call job_posts
and the message will land on the helper method on the controller, which is the expected behaviour.
Here, however, expect
is setting an expectation and, at the same time, stubbing a method on the view
with a fixed return value. Since the view template will call that method, the test passes.
About that unexpected "stub" side effect of expect
, I've found this in the rspec-mocks readme:
(...) We can also set a message expectation so that the example fails if find is not called:
person = double("person") expect(Person).to receive(:find) { person }
RSpec replaces the method we're stubbing or mocking with its own test-double-like method. At the end of the example, RSpec verifies any message expectations, and then restores the original methods.
Does anyone have any experience with this specific use of the method?