In my simplified example of what I’m actually doing, let’s say I have 2 calls to the database:
Repo.add( something_stringy )
Repo.remove( something_floaty )
and I want to use mocks for the database calls, as the real calls will be tested elsewhere:
let(:repo){
repo = double("Repo")
repo.should_receive(:add).with(instance_of(String))
repo.should_receive(:remove).with(instance_of(Float))
repo
}
before { FakeKlass.const_set :Repo, repo }
that’s all fine and dandy, but now if I wrap the calls in a transaction I’m a bit stumped:
Repo.transaction do
# ... some error checking in here somewhere...
Repo.add( something_stringy )
Repo.remove( something_floaty )
end
because if I write a mock that receives transaction it will receive the call, but everything in the block won’t get called, and I get:
expected: 1 time
received: 0 times
for all of the other mocks. Would anyone be able to show me how I should be writing my spec to deal with this? I’ve tried reading the relevant page in the RSpec book on around(:each) but that was about as clear as mud to me.
Any help is much appreciated.
You can use
#and_yieldto yield from an expectation chain:You also don’t need to set up a double to stub out methods on your Repo class. For example, your setup could be written:
You might also consider using
stubinstead ofshould_receive, as it doesn’t set up expectations:In general, you should only use
should_receivewhen you want to test the interaction between two objects. My own personal rule of thumb is that if it appears in abefore, usestub; if it’s in an example, especially with a specific value, useshould_receive.