Introduction
to Unit Test Mocking using Moq
The combination of dependency injection and mocking allows us to unit test modules which previously would have to be covered in integration testing – methods which call off to other multiple resources and perform processing on the results, for instance.
Being able in invert control, and inject these dependent service objects into the service module means we can substitute test objects at test-time. Mocking frameworks then save us the trouble of having to stub or mock out replacement dependent classes – and they also offer other functionality for testing behaviour as shown later.
A
simple example
We have a service class called Domain. A web page or program requires that the Domain class can provide the average of a set of numbers in a database. The calling class doesn’t want or need to know where it gets them, or what it does to them, so with the OO idea of encapsulation in mind, it offers a single method GetAverage().
public class Domain
{
private DAL dal;
private Calc calc;
public Domain()
{
this.dal = new DAL();
this.calc = new Calc();
}
public float GetAverage()
{
int[] numbers = this.dal.GetNumbers();
float average = this.calc.CalcAverage(numbers);
return average;
}
}
The above class has two private resources (dependent objects) – a data access class - DAL - and a calculation class - Calc. In the constructor of Domain, these are instantiated so that they are available to the GetAverage method, which uses each one once.
To use the Domain class and method in a piece calling code would be
Domain d = new Domain();
float average = d.GetAverage();
This is an example of tight coupling,
because to use Domain means you have to use DAL and Calc too – you have no
choice. This means that you cannot unit
test this, because any test of Domain would be testing DAL and Calc at the same
time, which is not unit testing. If DAL accessed a database, this would make the
test fragile and dependent on external resources.
In traditional testing, separate unit tests for DAL and Calc would be written, and
testing of Domain would be covered under Integration testing, which is often less thorough in terms of
scenario testing than unit testing. Some
paths within Domain might be missed by this since it is difficult to
integration test every scenario. It
would be useful if we could unit test Domain thoroughly.
Overcoming
dependency by Injection
The idea behind Inversion of Control in general, and Dependency Injection in particular is that classes do not tightly define which service classes they call. They handle service classes by referring to their interface type, not the concrete class. At instantiation, the actual concrete service classes are injected into the class. This allows us to substitute mock classes at test time.
Dependency injection can be achieved in many ways. There are commercial products which provide a framework which when you refer to an interface in code, the framework provides the concrete class. These mapping are defined in a separate piece of code within the framework.
Rather than introduce the complexity of a commercial IoC framework, I’ll use “poor man’s DI” to demonstrate the principles.
public class Domain
{
private IDAL dal;
private ICalc calc;
public Domain(IDAL dal, ICalc calc)
{
this.dal = dal;
this.calc = calc;
}
public float GetAverage()
{
int[] numbers = this.dal.GetNumbers();
float average = this.calc.CalcAverage(numbers);
return average;
}
}
The two changes to the example code to support DI are:
1.
The local resources are typed
to the interfaces IDAL and ICalc not the concrete
implementations of these classes. This
means they can hold not only the concrete implementations, but any mocked
versions we use for test as long as the they implmenet the interfaces.
2. The constructor is now ‘greedy’ – that is, anyone instantiating the Domain object must also supply concrete implementations of the Dal and Calc classes – thus inverting the control of which dependencies to use from the Domain class to the calling class.
An
aside about Encapsulation
Those new to Dependency Injection usually worry about encapsulation at this point. As a principle of Object design, it is good practice that calling classes should not need to know about the implementation details of a service class. But by forcing the calling class to use a greedy constructor, it has to know about them:
Domain d = new Domain(new
Dal(), new Calc());
float average = d.GetAverage();
This breaks encapsulation, since the calling class (which could be a web page code behind, for example) now needs to know about implementation-specific dependent classes (DAL and Calc) in order to use the class. This is generally a Bad Thing, because we’ve simply moved the coupling up a level in the object graph to the calling class.
IoC frameworks get around this by two main methods (there are variations, but these two are the popular ones)
1. Service Locator pattern
We provide a static lookup class which uses the IoC framework to convert an interface to a concrete class. In our example, we revert the constructor to the original no-argument version and use the static lookup class to initialise the concrete versions, e.g.
public Domain()
{
this.dal = ServiceLookup.Resolve<IDAL>();
this.calc= ServiceLookup.Resolve<ICalc>();
}
This pattern means we no longer have to inject the concrete classes from the calling code; the IoC framework will inject them when the Service Locator is called.
2. Greedy constructor argument injection
One of the best features of IoC frameworks is that they support automatic greedy injection. In our calling class when we ask for an IDomain object, the IoC framework will provide a concrete Domain object (if it is mapped) but it will also choose the greedy constructor version of its constructor, and provide all the parameters automatically, e.g. in our example, go back to the greedy constructor:
public Domain(IDAL dal, ICalc calc)
{
this.dal = dal;
this.calc = calc;
}
And when we call for an IDomain in the calling class…
IDomain d = ServiceLookup.Resolve<IDomain>();
float average = d.GetAverage();
... the IoC framework provides a concrete Domain object, but it has also called the greedy constructor of that object automatically, and provided concrete Dal and Calc classes as parameters. The result is that we haven’t had to instantiate the DAL and Calc classes in code anywhere (and definitely not in the calling code).
Since the Domain object was
provided by IoC, it has cleverly instantiated and provided
the injected dependent classes at the same time. If those dependencies had dependencies too,
it would have called the greedy constructors on them too and provided concrete
classes, and so on recursively.
Both of these methods mean that we have preserved the calling classes ‘ignorance’ of the dependencies. How the dependencies are wired up can be defined in a separate IoC container class. This means two things – we can wire up the classes dynamically if we like, which allows us to create configurable objects (Factory pattern), and more importantly for this essay, we can wire up mock test classes as dependencies.
Back to the example
Since I’m not going to go into the detail of implementing this with an IoC framework, I’ll live with the fact that the calling class has to instantiate the two injected service classes. Using an IoC container can alleviate this problem in a real development.
Domain d = new Domain(new
Dal(), new Calc());
float average = d.GetAverage();
The advantage of injecting the dependencies in this way is that when it comes to writing a unit test for the GetAverage method, we can now inject our own mocked dependencies.
In the pre mocking days, we would literally write stubs for the classes, inherited from the same interface as the real classes. These stubs could then be passed in via the injection, and the class would use our stubs instead of calling real resources. If we wanted to be extra clever, we could write the stubs to return a fake value when the methods were called, and thus stubs became mocks – no longer just placeholders, but attempting to mock the behaviour of the real object.
The disadvantage of this was that the mocks themselves became large, clumsy and could contain their own errors. If an interface insisted on a lot of methods and properties, your hand-crafted mock had to stub out all the method names and property names, even if you weren’t going to test them. You were writing a lot of extra code simply to support testing and this is also a Bad Thing.
Mocking frameworks
So came along the idea of a mocking framework to avoid all this extra code and work. Rhino Mocks, NMock and Moq are examples of popular mocking frameworks. There are advocates and critics of all of them, but they basically all do the same thing –they provide a way of quickly assembling mock objects to inject into classes, so you don’t have to write them yourself. They also provide advanced verification methods which hand-crafted mocks would find difficult, which we will see later.
Moq is one of the latecomers, being relatively new. One advantage it has is that it has leveraged the fluent interface allowed by LINQ expression trees. This means it is very simple to use, even for the beginner.
There are three things we might want a mock to do:
1. Take the place of a dependent class so we don’t test anything except the system under test.
2. Vary the value returned from a mock depending on the arguments passed to it
3. Verify behaviour, e.g. which methods on the dependency were called, how many times, etc.
Take the place of a
dependent class
To achieve 1, within our test method, we simply create a mock object and inject it into the constructor of our System Under Test:
[TestMethod()]
public void GetAverageTest()
{
// Given
var mockDal = new Mock<IDAL>();
var mockCalc = new Mock<ICalc>();
// When
Domain sut = new Domain(mockDal.Object, mockCalc.Object);
float actual = sut.GetAverage();
// Then
Assert.Inconclusive("Hard To test.");
}
As shown above, instantiating mock objects is simple. When we want to use the mock as a concrete class in the argument list of the class constructor, we use the .Object property. (In reality, this uses an internal version of IoC to provide a proxy class with appropriate mocked methods and properties as defined in the interface)
At the moment, we still can’t really test the result coming back from the method call, because the mocked objects would not have been returning real values when used within the class. By default, class methods which are being mocked will return default<T> of the return type. This test might even throw an exception if the code was expecting DAL to return a populated array of ints and subsequently called the .length property on a null, for instance.
Vary the value returned
So to achieve 2, predictable results coming from the mock, we can set it up to return something sensible instead of default<T>, using the Setup method:
// Given
var mockDal = new Mock<IDAL>();
mockDal.Setup(x =>x.GetNumbers()).Returns(new int[] { 1, 2, 3 });
This means that when GetNumbers method on the mocked DAL is called with no parameters, then the mock will return a new int array with 1,2,3 as members. We do this before we inject or use the mock. When the mocked DAL is called by the Domain class, then it will get back this defined array, as if the code had really executed.
We can do the same with the mocked Calc, making it return a fixed float value of 3.5
var mockCalc = new Mock<ICalc>();
mockCalc.Setup(x => x.CalcAverage(It.IsAny<int[]>())).Returns(3.5f);
Note that the real CalcAverage takes a parameter, so the mock would be called with a parameter. In this case, we use the Moq syntax for ‘any int array’ which is
It.IsAny<int[]>()
You can substitute any type for the int[] – this means that you can test overloaded methods with separate Setup lines. If you wanted to test for a specific value, you can use the value instead of the It.IsAny clause. You can have as many Setups on a single mock as you require. This allows you to configure the mock to return specific values depending on input, either specific values or ‘any’ value of a type.
It also avoids the mocked class giving back nonsense default<T> results within your test class when it is run, which may have broken the test. In this way we can add a usual Assert statement to the test, to test the output value (in this case 3.5).
The final thing we may want our mock to do is to allow us to verify how the dependency was called during the test execution. We may wish to verify that certain methods were called, and how many times each one was called.
In our example, as well as asserting that the result from the main method was 3.5, we may want to ensure that during execution, DAL.GetNumbers() was called once, and Calc.CalcAverage() was called once. We can do this by post-test verification calls on the mocks:
// Then
Assert.AreEqual(3.5f, actual);
mockDal.Verify(x =>x.GetNumbers(), Times.Once());
mockCalc.Verify(x =>x.CalcAverage(It.IsAny<int[]>()), Times.Once());
So using the Verify methods on the mocks, we can check that certain methods with certain parameters were called during execution. As above, we can check for absolute values for the parameters, or It.IsAny as a placeholder for any type.
The Times object has many variants: Times.Exactly, Times.AtLeast, Times.Never, Times.Between, etc, so complex behaviour can be tested. When the verify fails, the test fails, just like a normal Assert statement.
This allows us to test the behaviour of the system under test, with regards to how it is using its dependent classes.
Conclusion
Dependency Injection and mocking together provide a powerful way to increase test code coverage on complex classes with dependencies, which before would have been difficult to unit test. The use of mocking frameworks, such as moq, allows behavioural testing to be added to the state-based testing suite.