Mocks, Stubs and Partials
RSpec will create mocks and stubs for you at runtime, or attach stub/mock behaviour to any of your real objects (Partial Mock/Stub). Note that the underlying implementation for mocks and stubs is the same, and you can therefore intermingle mock and stub behaviour in either. There is a semantic difference in how they are created, however, which can help clarify the role it is playing within a given spec.
Mocks
Mocks are objects that allow you to set and verify expectations. They are very useful for specifying how the subject of the spec interacts with its collaborators. This approach is widely known as “interaction testing”.
Mocks are also very powerful (though less widely understood) as a design tool. As you are driving the implementation of a given class, Mocks provide an amorphous collaborator that can change in behaviour as quickly as you can write an expectation in your spec. These changes are tantamount to designing the interface to a collaborator that often does not yet exist. As the shape of the class being specified becomes more clear, so do the requirements for its collaborators – often leading to the discovery of new types that are needed in your system.
Read Endo-Testing for a much more in depth description of this process.
Stubs
Stubs are objects that allow you to set “stub” responses to messages. As Martin Fowler points out on his site, Mocks aren’t stubs. Paraphrasing Fowler’s paraphrasing of Gerard Meszaros: Stubs provide canned responses to messages they might receive in a test, while mocks allow you to specify and, subsquently, verify that certain messages should be received during the execution of a test.
Partials
RSpec also supports Partials, allowing you to add stub/mock behaviour to instances of your existing classes. This is generally something to be avoided, because changes to the class can have ripple effects on seemingly unrelated specs. When specs fail due to these ripple effects, the fact that some methods are being mocked can make it difficult to understand why a failure is occurring.
That said, Partials do allow you to expect and
verify interactions with class methods such as :find and :create
on Ruby on Rails model classes.
Notes
There are many different viewpoints about the meaning of mocks and stubs. If you are interested in learning more, here is some recommended reading:
- Mock Objects: http://www.mockobjects.com/
- Endo-Testing:http://www.mockobjects.com/files/endotesting.pdf
- Mock Roles, Not Objects: http://www.mockobjects.com/files/mockrolesnotobjects.pdf
- Test Double Patterns: http://xunitpatterns.com/Test%20Double%20Patterns.html
- Mocks aren’t stubs: http://www.martinfowler.com/articles/mocksArentStubs.html