I’m testing some methods that involve email, and am trying to use a mock mailer object. I’m obviously going about it the wrong way, because the test works the first time but the very same test fails subsequently. I’d appreciate it if anyone can explain what is going on here. Thanks.
describe SentMessage do
before(:each) do
Notifier ||= mock('Notifier', :send_generic => true)
end
it "Sends an email" do
Notifier.should_receive(:send_generic).with(['a@contact.com'], 'test')
Notifier.send_generic(['a@contact.com'], 'test').should_not be_nil
end
it "Sends an email" do
Notifier.should_receive(:send_generic).with(['a@contact.com'], 'test')
Notifier.send_generic(['a@contact.com'], 'test').should_not be_nil
end
end
Result:
Failures:
1) SentMessage Sends an email
Failure/Error: Notifier.send_generic(['a@contact.com'], 'test').should_not be_nil
expected: not nil
got: nil
# ./spec/models/test.rb:14:in `block (2 levels) in <top (required)>'
Rspec inserts setup/teardown stuff for mocks and expectations. This does stuff like verify that
should_receiveexpectations have been met and clear up mocks set in objects that endure beyond a single spec. For example if you had stubbed User.find in one spec, you wouldn’t expect that stub to exist in another spec.So at the end of the first spec, rspec is removing the stub setup in the before each. Because you’re doing ||=, Notifier isn’t recreated and neither is the stub. This in turn means that when you call should_receive in the second spec you’re setting up a new stub. Since this new stub has no specified return value, nil is returned.