Mock Object Frameworks
Posted by thehumbleprogrammer on August 1, 2008
In the last 18 months I have been doing a good deal of experimentation with mock object frameworks. Trying to understand mocking frameworks, when to use them and when not to has been a painful experience, but one that I feel everyone should go through in order to come out the other side, with a deep seated knowledge of building testable systems. This is the first in a series of posts explaining my understanding of mock objects and the frameworks out there.
Introduction
Substituting real implementations of an interface with a mocked implementation is a technique used in unit testing that gives you the following benefits:
- Keeps your unit tests fast running.
- Enables you to test your classes in isolation.
- Usually leads to a well designed loosely coupled system.
Fast running unit tests are essential to keeping the developers interested in running and maintaining test coverage during the development of a system. When I first tried unit testing a production system I soon became unstuck with tests that relied upon external resources that I had no control over such as database calls, SMTP, the file system etc. When this happens the tests become unrepeatable and slow, from then on other developers didn’t run the tests often, meaning that the test suite became an un trusted, maintenance nightmare with very little benefit. In order to keep your tests running fast you must mock out these external dependencies, tests that incorporate the database calls etc can, and should be included in an integration test suite that is separate from your unit tests. Points two and three are resulting side effects that are beneficial in their own right when you have a fast running, repeatable suite of unit tests.
The mistakes I made in the above mentioned project lead me down the path of Mock object frameworks. So far in this article I have used the term Mock to mean any type of implementation used as a substitute in your tests. There are several different types of Test Doubles that can be used, each of them enable you to take different approaches in your unit tests. Over this series of articles I will be delving more deeply into the different approaches to writing unit tests but for now I will use Martin Fowler’s definitions from his article Mocks Aren’t Stubs without going into too much detail.
Mock objects
pre-programmed with expectations which form a specification of the calls they are expected to receive
Stubs
provide canned answers to calls made during the test, usually not responding at all to anything outside what’s programmed in for the test. Stubs may also record information about calls, such as an email gateway stub that remembers the messages it ’sent’, or maybe only how many messages it ’sent’.
Fakes
objects actually have working implementations, but usually take some shortcut which makes them not suitable for production
A common example throughout these articles will be to develop a Presenter that collaborates with a view and a model (MVP), I will be substituting implementations of these dependent objects with mocks/stubs/fakes. This allows me to construct the presenter without worrying about the implementation details of the view and the model. In my opinion this is a very important benefit of mocking because it allows me to concentrate on doing one thing and one thing only.
The Manual Approach
The manual approach to achieving this isolation is to implement your own stubs that return test data when the methods are called. The following is a CustomerOrdersPresenter that interacts with an ICustomerOrdersView and an IDataProvider (the model). In the constructor of the presenter I want to attach to the views load event so my test for this is…
[Test]
public void Should_Attach_To_Load_Event()
{
ICustomerOrdersView customerOrdersViewStub = new CustomerOrdersViewStub();
CustomerOrdersPresenter presenter =
new CustomerOrdersPresenter(customerOrdersViewStub, _customersDataProvider);
Assert.IsNotNull(presenter, "Presenter should not be null");
Assert.IsTrue(((CustomerOrdersViewStub)customerOrdersViewStub).InvocationListCount > 0,
"the invocation list of the Load event should be greater than 0");
}
internal class CustomerOrdersViewStub : ICustomerOrdersView
{
//ICustomersView implementation
....
//added property for testing
public int InvocationListCount
{
get { return this.Load.GetInvocationList().Length; }
}
}
Finally the implementation of the CustomerOrdersPresenter’s constructor is
public class CustomerOrdersPresenter
{
private readonly ICustomerOrdersView _view;
private readonly IDataProvider _provider;
public CustomerOrdersPresenter(ICustomerOrdersView view) :this(view, new CustomerDataProvider())
{ }
public CustomerOrdersPresenter(ICustomerOrdersView view, IDataProvider provider)
{
_view = view;
_provider = provider;
_view.Load += new EventHandler(View_Load);
}
}
- No learning curve (we all know how to write code).
- Complete control over the stub
- Can quickly become a nightmare to maintain two sets of implementations.
- A lot of code to write just to get useful fine grained tests.
Although the downside to the manual method is quite significant I would advise anyone starting out unit testing to use it until they are completely happy with writing good unit tests. With hindsight I probably went over to mock object frameworks too early in my unit testing career, this lead to a lot of frustration with trying to learn two things at once.
Mocking Frameworks
In order to avoid writing your own stubs for testing purposes you can incorporate a mock object framework to do the work for you. As I said earlier I found the learning curve is pretty steep but as with all things it gets easier over time. Of course some of you geniuses out there will probably get it straight away, or you may have a colleague who has used the frameworks before. All I can say is give yourself a pat on the back and sit back with your hands cradling the back of your head allowing a nice smug grin to appear on your face.For the rest of us the different frameworks are:
- TypeMock
- Free and professional versions.
- Allows you to mock anything, including static methods.
- Has a fluent interface.
- pro version is quite expensive.
- You don’t have to inject mocked objects
- NMock2
- Free open source project.
- Allows you to mock classes and interfaces.
- Uses strings to set the expectations on method calls.
- Uses a fluent interface.
- You have to inject dependent mock implementations in order to set expectations on them.
- RhinoMocks
- Free open source project.
- Allows you to mock classes, interfaces and delegates.
- Developed with refactoring in mind, by using the strongly typed mock object’s instead of strings to set your expectations.
- Uses a fluent interface.
- You have to use Dependency Injection in order to substitute the real implementation with a mock/stub.
- MoQ
- Free open source project.
- Allows you to mock classes, interfaces and delegates.
- Uses strongly typed mocks when setting expectations.
- Uses a fluent interface.
- No record/replay/verify syntax
With the exception of MoQ all of the frameworks use a record/replay/verify model. This means that you record a set of expected behaviour then you verify that all of the expectations were met after the replay. The record/replay model is only important when you are using pure mock objects (not stubs) in an interaction based test. State based testing is the more familiar to most developers, where you set up some test data and call the unit under test and assert that the state of the object meets some post condition. When doing interaction based testing the assertions being made are based on the interaction between the unit under test and its’ collaborators. This will hopefully become clearer as I produce some demo code in later instalments of this series.
In the next article I will be delving into the reasons behind why I chose RhinoMocks. I will also be showing more code examples of writing unit tests using RhinoMocks.
Anthony Bouch said
Excellent article – look forward to the next in the series
thehumbleprogrammer said
Cheers T, it’s always good to have a reader, makes all the hard work worthwhile.
Mock Object Frameworks Part 2 « TheHumbleProgrammer said
[...] in Mock Object Frameworks, Test Doubles, Unit testing at 6:26 pm by thehumbleprogrammer In the first instalment of this series I introduced the idea behind mocking showing a quick example of hand rolling your [...]
Mock Object Frameworks Part 3 « TheHumbleProgrammer said
[...] in Mock Object Frameworks, Test Doubles, Unit testing at 5:49 am by thehumbleprogrammer In part 1 of this series I introduced the idea of substituting collaborating objects with test doubles in [...]
sayamasihbelajar said
hi…
love your articles about mocking frameworks. I learn a lot from them. Thanks for writing them up.
thehumbleprogrammer said
thanks for the feedback Saya.