This is the final post in the whole “Test Small Before Testing Big” saga. I’ve tried to impress upon any readers new to TDD the importance of writing code in small, easily testable chunk before assembling the parts into the whole. Writing small, understandable unit tests helps keep the debugger on the sidelines. I shared an example of unit testing an aggregate, looping operation that my team stumbled upon this Spring as an example of the importance of coding and testing from the bottom up. Lastly, I wrote a small piece about the importance of small unit tests with TDD in maintaining the mental state of “Flow.”
One of a Test Driven Developer’s best allies is the mock object. Mocks or stubs have always been one of the best tools to create smaller unit tests by providing a boundary condition of known behavior. What might not be as obvious is the usage of mock objects as a design tool and a mechanism to maintain that all important productive Flow.
A particularly pernicious TDD flow killer is when you’re writing unit tests for a class and realizing you need changes in another class first. A little of this isn’t a big deal, but it’s still context switching and it’s inefficient. You can, and I think should, try to come up with a list of changes throughout a class structure to make in any coding session, but there is a definite point of diminishing returns. Even if you do some upfront thinking you’ll still discover ancillary tasks you didn’t anticipate when you’re coding (that whole “not being omniscient thing” is inconvenient). My point being is that it’s going to happen and you need to be able to deal with the context switching. My answer is to use Mock objects (or stubs) to stand in for the missing functionality so I can worry about the newly discovered task later. Basically, I’m throwing in a point of mocking as a TODO so I can keep moving forward with the task I’m working on at the moment.
A couple of weeks ago I was working on a Presenter class in a new ASP.Net application that needed to drive a typical cascading dropdown list. I had been concentrating on the page workflow and the backend services and had probably forgotten all about the dropdowns. Getting the data to build the lists for the dropdown boxes was more complicated than it should be, so if I stopped to code the list building functionality I would have lost the flow of the Presenter class I was working on at the time. No bother. On the spot I created a new interface called IAddressBookService that would hold the responsibility for fetching and assembling the lists. I then went right back to the Presenter unit tests and simply added a mock object for the new interface that was injected into the Presenter’s constructor function and setup the proper expectations.
public interface IAddressBookService
ListItem FindSendersForReviewer(string receiverId);;
Here’s a snippet from the unit test (using RhinoMocks):
MockRepository mocks = new MockRepository();;
IAddressBookService addressBook = (IAddressBookService) mocks.CreateMock(typeof (IAddressBookService));
ListItem items = new ListItem
new ListItem(“a”, “b”),
new ListItem(“c”, “d”)
// Verify that the Presenter pushed the receiver list into the
Once the Presenter logic and workflow was working correctly I switched to a concrete implementation of the IAddressBookService and tested that in isolation. Lastly, I built the ASPX page and wired the Presenter and the concrete IAddressBookService implementation together. The cascading dropdowns worked on the first try. One of the very cool things about using MVP architectures is that you will not uncommonly have a correctly functioning screen on the first try.
Mock objects are a Design Tool
I sometimes like to think of mock objects as the TDD equivalent of drawing a UML sequence diagram, except in code. Mock objects can be used to define a new interface by simply working through the requirements of its client. In the example above I let the needs of the Presenter class completely define the required interface of the IAddressBookService interface without particularly worrying about the implementation. The interaction between the Presenter, the IAddressBookService, the ASPX view, and the backend services could be described in unit test code before any were implemented. It’s an awfully powerful device to understand the interaction between disparate parts of your application before you go too far down a path that won’t work. In the past I have abandoned or changed an intended design because of the knowledge gained by writing interaction-based tests with mock object standins.
In a previous post I talked a little about doing development “client-first.” I’m a firm believer in the “code from the bottom up” mantra, but once again, software is not construction. Sometimes it’s just easier to start somewhere in the middle. In my case, I understood the Presenter workflow the best, so I started there and let that workflow define the interface requirements of both the view and the list building.
One last thing, I could have shoved the list building into the Presenter, but does that functionality really fit there? The unit tests were more cohesive with the list building behind an interface. Looking at the code from a distance, it seems like a slam dunk to move the list building to a separate responsibility, but the unit testing alone made that clear. I guess what I’m trying to say is, if you think it would be easier to write a unit test if a certain piece of the code wasn’t there, it’s probably a different responsibility that should be elsewhere anyway.