Method Stubs
In addition to the more standard Mock Object framework, RSpec also supports stubbing return values to messages on any object (including Classes and mocks!). Stubs do not support any arguments. You simply set up a return value and forget about it. If you need more control, take a look at partial mocking.
The main difference between a stub and a mock is that mocks verify interactions that you expect, while stubs just sit there and return values.
Setting an explicit return value
This is the simplest (and recommended) approach to stubbing.
my_instance.stub!(:msg).and_return(value)
MyClass.stub!(:msg).and_return(value)
Calculating a return value
my_instance.stub!(:msg).and_return { ... }
MyClass.stub!(:msg).and_return { ... }
While this is possible, it is generally to be avoided. Calculating a value to return defeats the declarative nature of stubs.
Multiple return values
my_instance.stub!(:msg).and_return("1",2)
MyClass.stub!(:msg).and_return("1",2)
This will return “1” the first time it is called and 2 every subsequent call. Like calculated return values, this is a little un-stubby, but it can be a handy feature once in a while.
Mixing stubs and mock messages
In some cases it can be helpful to stub a default return value, but set a mock expectation for a specific set of args. For example:
A.stub!(:msg).and_return(:default_value)
A.should_receive(:msg).with(:arg).and_return(:special_value)
A.msg
=> :default_value
A.msg(:any_other_arg)
=> :default_value
A.msg(:arg)
=> :special_value
A.msg(:any_other_other_arg)
=> :default_value
A.msg
=> :default_value