Testing with Mock Objects
When you write JUnit tests you can run them as often as you like to because they run fast to give you the "green light" confidence. However, once you've written and maintained JUnit tests for real-world applications you quickly realize classes and methods under test call on other classes and methods, which maybe hard to set up or take time to execute. Enter mock objects.
So you've heard of mock objects and you'd like to use them in place of real objects so you can isolate and test one class and one method at a time. The basic idea is as simple as that but once you delve in you'll find a few unexpected turns. There is sufficient information on the Internet but it's somewhat decentralized. Here you'll find a brief overview and the basic facts to get you started as well as pointers to essential resources.
The term mock objects was coined by Tim Mackinnon, Steve Freeman and Philip Craig. It was presented at the XP2000 conference in the paper Endo Testing: Unit Testing with Mock Objects.. The paper still makes a good read but it doesn't have to be the place to start from. I recommend checking out the brief tutorials for either the EasyMock or the JMock implementations listed below.
Mock objects is a general term. There are several flavors and implementations - all of them are open source software:
- EasyMock - automatic generation of mock objects from a Java interface or a Java class (through EasyMock Class Extension); the documentation link on the EasyMock website is a good, brief tutorial.
- Mockquer - an extension of EasyMock allowing mock objects to be generated based a class, not just an interfaces. In fact EasyMock has the EasyMock Class Extension that allows you to just that so I'm not sure what this implementation adds.
- JMock - similar features to those provided in EasyMock but uses a different, more flexible paradigm for recording expectations on mock objects (i.e. what methods the class under test will invoke on the mock objects).
- Mock Objects - with this implementation mock objects are not generated on the fly but are instead created either manually or using code generation tools; besides a slim FAQ there was little documentation I could find; the website however tries to be something of a portal and contains a number of links to other mock object implementations. The book "Test-Driven Development - A Practical Guide" by David Astels has a chapter on Mock Objects.
Once you've began looking at the details you realize mock objects aren't just stubs. They're also capable of recording a replay sequence of the methods and values they're expected to be invoked with. For an excellent discussion of this check out Martin Fowler's Mocks Aren't Stubs.
The following article presents experiences from extensive use of mock objects on a medium-sized project Unit Testing with Mock Objects
Mock objects aren't the only solution to the problem. The Object Mothers pattern suggests an alternative where real objects can be easily created and managed by carefully organized test code. This is a very useful discussion even if you're set on using mock objects. However, I believe in some limited situations mock object may still be necessary to eliminate code that's not under test.
Finally, here is an article that discusses how to complement mock objects with aspect oriented programming: Test flexibly with AspectJ and mock objects.