Idealism is what precedes experience; cynicism is what follows...

Sunday, June 15, 2008

Mock Frameworks, not for everyone and everytime

A frequent question is when should I use a mock object framework ?
However, if you have to ask "when", the answer is probably "not now". I feel that mock object frameworks are something you have to evolve into.

First, we can talk about mocks in general. Some people have a misconception that mock objects are only useful if you need to simulate interaction with a resource that is difficult to use in unit tests - like an object that communicates with an SMTP server. This isn't true.

* The real object has nondeterministic behavior
* The real object is difficult to setup
* The real object has behavior that is hard to trigger
* The real object is slow
* The real object is a user interface
* The real object uses a call back
* The real object does not yet exist

If we were to step back and generalize this list, we'd say test doubles are useful when you want to isolate code under test. Isolation is good. Let's say we are writing tests for a business component. We wouldn't want the tests to fail when someone checked in bad code for an auditing service the business component uses. We only want the test to fail when something is wrong with the business component itself. Providing a mock auditing service allows us to isolate the business component and control any stimuli the component may pick up from its auditing service. When you start feeling the pain of writing numerous test doubles by hand, you'll know you need a mock object framework.

Mocks aren't just about isolation, however. Mocks can play an important role at any time if employed correctly. Mocks can be powerful technique for identifying types in a system based on the roles that objects play … In particular, we now understand that the most important benefit of Mock Objects is what we originally called interface discovery.

Using a mock object framework allows a continuous, top-down design of software. But Aren't Mock Object Frameworks Complex?

This is another question I've been asked recently. Mock object frameworks are actually rather simple and expose a small API. There is complexity, though, just not in the framework itself. As I said earlier, I think there is a path you can follow where you evolve into using mock object frameworks. The typical project team using a mock object framework is experienced with inversion of control containers. Trying to get up to speed on all these topics at once can be overwhelming.

There is also some complexity in using mocks effectively. In Mocks and the Dangers of Overspecified Software, Ian Cooper says:

"When you change the implementation of a method late in the implementation process, mocks can break because you now make additional or different calls to the dependent component that is being mocked. … The mocks began to make our software more resistant to change, more sluggish, and this increased the cost to refactoring. As change becomes more expensive, we risked becoming resistant to making it, and we risk starting to build technical debt. A couple of times the tests broke, as developers changed the domain, or changed how we were doing persistence, without changing the test first, because they were frustrated at how it slowed their development. The mocks became an impedance to progress."

Mock object frameworks make interaction based testing easy, but can also lead to the problems Ian outlines. Here a couple more reads on this topic:

* Guidelines to Using Interaction Based Testing
* Why Mock Frameworks Suck

In summary – mock object frameworks aren't for everyone. You'll know when you need one!

No comments:

Blog Archive

My Network