Using rspec, confused as to difference between a mock and a stub object?
Wha开发者_如何学JAVAt is the difference between a mock and a stub, they both seem very similar to me?
It would be nice if someone could give a real world example of when to use which, or are they interchangeable but there is a best-practise like when to use a mock or a stub?
This is the reference in most articles, pretty generic and clear explanation:
http://martinfowler.com/articles/mocksArentStubs.html
In a nutshell:
Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test. Stubs may also record information about calls, such as an email gateway stub that remembers the messages it 'sent', or maybe only how many messages it 'sent'.
And
Mocks are objects pre-programmed with expectations which form a specification of the calls they are expected to receive.
The article provided and the question asked come from different contexts. Regarding the realm of Rspec, the authors of The Rspec Book write in ch 14.1:
"To create a double, just use the double()
method, like this:
thingamajig_double = double('thing-a-ma-jig')
... There are also stub()
and mock()
methods, which produce the same kind of object:
stub_thingamajig = stub('thing-a-ma-jig')
mock_thingamajig = mock('thing-a-ma-jig')
We can use those to make the spec clearer when appropriate." (emphasis mine)
The authors also include a code snippet later in ch 14.3 -
describe Statement do
it "logs a message on generate()" do
customer = stub('customer')
customer.stub(:name).and_return('Aslak')
logger = mock('logger')
statement = Statmement.new(customer, logger)
logger.should_receive(:log).with(/Statement generated for Aslak/)
statement.generate
end
end
and then write "By using the mock()
method to generate the logger double and the stub()
method to generate the customer double, we're helping to express that these objects are playing different roles in the example." (emphasis mine)
These code snippets and explanations lead me to believe that while the conceptual lines drawn by Mr. Fowler in his article are good ones to draw, there is no functional difference between stub()
or mock()
( or double()
, for that matter) in Rspec. Could be wrong though, I haven't checked the documentation.
stub:
A fake object that returns a pre-determined value for a method call.
Actual object is not called.
Stubs and mocks often used interchangeably.
Mean two different things.
But people generally refer to "Mock Object Frameworks"
Product.stub(:find_by_title).with('orange').and_return(Product.new(:title=>"orange", :price=>6.23))
Mocks:
Just like Stubs, but with an expectation to be (or not to be) called.
Test will fail if the mock is (or isn't) called.
Used in the same way as stubs,
Product.should_receive(:find_by_title).with('orange').exactly(2).and_return(Product.new(:title=>"orange", :price=>6.23))
To know more about mock and stub please refer this article,
http://www.ibm.com/developerworks/web/library/wa-mockrails/index.html
精彩评论