Stubbing sequential method calls with RR

Journal entry
October 6, 2010

I recently found myself with the need to have a stubbed method return different values depending on the order it was called in. So that the first time the method is called, it returns one thing and the next time it returns another.

With Mocha this is neatly done using Exception#then:

object.stubs(:expected_method).returns(1, 2).then.returns(3)

However, I am using RR and that doesn’t provide any syntactic sugar for this. Thankfully, Laust showed me a way that is almost as clean:

values = [42, 37, 3.14]
stub(object).counter do
  values.shift
end
object.counter # => 42
object.counter # => 37
object.counter # => 3.14

This is useful if for example you need to mock out that a model can only be saved once, and it’ll raise an exception after the first save:

results = [lambda{ true }, lambda{ raise "Cannot be saved twice" }]
mock(model).save.times(results.size) do
  results.shift.call
end
model.save # => true
model.save # Raises an exception
Categories
Selling out
Did you know?
Jakob is an independent web application developer who builds awesome stuff for the web. You can hire him to build awesome stuff for you.

Comments and Trackbacks

Commenting on this entry has been closed.