Just got through reading the mockobjects article on the interaction test smell too many expectations.
It's a great article and made me want to try to bring together my understanding of what people mean when they talk about stubbing and mocking.
MockObjects.com - Stubs and Expectations
The article makes the distinction between Stubs and Expectations:
- Stub - Replace a dependend on component (DOC) so that you can get it to return known values.
- Expectation - Goes further by testing that we get the expected interaction with the DOC.
The idea is that if you program too many expecations into the test you get confusing tests that don't make it clear whats important.XUnit Test Patterns - Stubs and Mock Objects
If you have read Meszaros's XUnit Test Patterns then you will know that in his view there are multiple types of Test Double and they are required to control two things:
- Indirect Inputs - If the system under test (SUT) uses the DOC and the DOC returns any values (even exceptions) that affect the SUT then you need to be able to make the DOC return these values in order to run your tests. If you can't get the DOC to do it then you replace it with a Test Double.
- Indirect Outputs - Encapsulation often means we don't have to care how an object does what it does, however when testing we do care and we therefore may want to test the interactions with the DOC (in the process writing the SUT to make its dependency on the DOC more obvious). In fact in some cases we may have no choice if the DOC does not produce any observable side effects.
Meszaros goes further and describes the means of getting the correct inputs into the SUT in as being through a control point and the means of verifying the indirect outputs as being through an observation point.
In Meszaros's terminology there are thus three main types of Test Double:
- Test Stub - Controls indirect inputs to the SUT.
- Test Spy - Acts as a Test Stub but also records calls so that the test can examine them.
- Mock Object - You pre-program it with the expected interactions and it will verify they happened.
Meszaros also discussed further classifications and how to configure/install the Test Doubles, as with the rest of the book it is very comprehensive.
Why It Matters
It seems like people are coming to the conclusion that it is important to differentiate between situations where you care about the expected interaction with an object and cases where you don't. If you don't make the differentiation your tests will be unnecessarily complex.
The interesting bit is then how the different types of Test Double affect your testing. I believe many people use Mock Objects when they really don't much care about the collaborations and aren't using the mocking as an aid to design. In fact the mock object is often simply there to replace a DOC so that we can simplify or speed up the test. This is at odds with the design technique that mockobjects.com and "Mock Roles, Not Objects" are recommending. As I understand it they view the outside-in process of design as being a big advantage of using interaction tests and use that to drive their designs (Need-Driven Development).
Its the second issue, how tests affect design, that interests me at the moment.