- A Web of Objects
- Values and Objects
- Follow the Messages
- Tell, Don't Ask
- But Sometimes Ask
- Unit-Testing the Collaborating Objects
- Support for TDD with Mock Objects
Unit-Testing the Collaborating Objects
We appear to have painted ourselves into a corner. We're insisting on focused objects that send commands to each other and don't expose any way to query their state, so it looks like we have nothing available to assert in a unit test. For example, in Figure 2.4, the circled object will send messages to one or more of its three neighbors when invoked. How can we test that it does so correctly without exposing any of its internal state?
Figure 2.4 Unit-testing an object in isolation
One option is to replace the target object's neighbors in a test with substitutes, or mock objects, as in Figure 2.5. We can specify how we expect the target object to communicate with its mock neighbors for a triggering event; we call these specifications expectations. During the test, the mock objects assert that they have been called as expected; they also implement any stubbed behavior needed to make the rest of the test work.
Figure 2.5 Testing an object with mock objects
With this infrastructure in place, we can change the way we approach TDD. Figure 2.5 implies that we're just trying to test the target object and that we already know what its neighbors look like. In practice, however, those collaborators don't need to exist when we're writing a unit test. We can use the test to help us tease out the supporting roles our object needs, defined as Java interfaces, and fill in real implementations as we develop the rest of the system. We call this interface discovery; you'll see an example when we extract an AuctionEventListener in Chapter 12.