BlackWaspTM

This web site uses cookies. By using the site you accept the cookie policy.This message is for compliance with the UK ICO law.

Testing
.NET 3.5+

Using Mocks

The fourteenth part of the Automated Unit Testing tutorial concludes the description of isolating a class from its dependencies using test doubles. This article explains how mock objects can be used to fake large classes and to test expected behaviour.

What are Mock Objects?

In the previous two articles in this series we have looked at stubs and fakes. These are types of test double, which are substituted for real dependencies during testing in order to isolate the code under test. Isolation allows us to create unit tests without the setting up dependencies beforehand, which could be too complex to be viable. In this article we will consider a third type of test double, known as a mock object or mock.

Mock objects are usually provided by isolation frameworks. For .NET developers, an isolation framework is generally a referenced assembly that you use to automatically create proxy objects. These are objects that implement an entire interface, or inherit the functionality of a class, without the need for further code. In this raw state, mock objects can be used as dummy objects, used to fill parameters with values that will not be used in a test. However, the power of mocking comes from programming the proxies with expectations.

When you add an expectation to a mock object, you tell it that it should expect a specific call. For example, if you are testing a class that calculates the balance of an account, based upon transactions retrieved from a database, you might mock the data access class. You could then add an expectation that the "GetTransactions" method will be called with specific arguments. The expectation can be set up to return a known set of transactions, acting in a similar manner to a stub. Additionally, you can verify that the expected call was made in a test and have the test fail if it was not.

Moq Isolation Framework

There are many popular isolation frameworks available for .NET developers. As with testing frameworks, they vary in functionality and complexity of use. Some are free to use and provided under an open source license, whereas others are commercial products.

In this article I will describe some examples of mocking using the Moq framework. The examples will be created using version 4.0, which is the latest version at the time of writing. Moq is a personal preference as I like its ease of use and the style used for programming the mocks, which uses strong typing and so gains Intellisense support. Moq is also free to download and is an active open source project. It can be used to create proxies for both interfaces and non-sealed classes but not static classes or static members.

One downside to Moq is that, because it uses lambda expressions, it is not suitable for early versions of the .NET framework. If you develop using Visual Studio 2003 or 2005, you will need to obtain another isolation framework.

Creating Mock Objects

In order to demonstrate the mocking with Moq, we need some code to test. The following shows a class that calculates an account balance, based upon a starting value and a set of transactions. The calculation is performed for either for a single period or for a series of numbered periods. The transactions are retrieved from a dependency that implements the ITransactionRetriever interface. This is the interface that we will mock, as in the real system it would access a database.

The tests for the BalanceCalculator class will use mocked ITransactionRetriever objects to demonstrate how expectations can be created and verified. We will also verify that calls were made without creating expectations beforehand. The examples will show the basic use of Moq. In future articles I will describe further mocking techniques.

public class BalanceCalculator
{
    ITransactionRetriever _retriever;

    public BalanceCalculator(ITransactionRetriever retriever)
    {
        _retriever = retriever;
    }

    public decimal GetBalance(decimal startBalance, int period)
    {
        try
        {
            decimal[] transactions = _retriever.GetTransactions(period);
            return transactions.Sum() + startBalance;
        }
        catch (ArgumentException)
        {
            return startBalance;
        }
    }

    public decimal GetBalance(decimal startBalance, int startPeriod, int endPeriod)
    {
        decimal runningTotal = startBalance;
        for (int period = startPeriod; period <= endPeriod; period++)
        {
            runningTotal = GetBalance(runningTotal, period);
        }
        return runningTotal;
    }
}

public interface ITransactionRetriever
{
    decimal[] GetTransactions(int period);
}

Adding Moq to the Test Project

Once you have downloaded Moq you will find that it includes several versions, each targeted at a particular version of the .NET framework. Each includes an assembly named "Moq.dll". You should add a reference to this DLL in your test project. To simplify the code, also add the following using directive to any test class that uses mocks:

using Moq;
15 May 2011