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+

Moq Partial Mocks

Moq is commonly used to create mock objects based upon interfaces. However, it can also be used to mock classes. This includes the possibility of creating partial mocks, where some members are intercepted with expectations whilst others run as normal.

Mocking the Class Under Test

You can use partial mocks to mock the class under test. Sometimes, as in the updated MarsLander class, there are members that are difficult to control. The results of these members can be made predictable by adding expectations. You can then test the methods that depend upon those results within the same class.

Consider the updated test below. Here we are working with a partial mock of the MarsLander class only. We wish to test that the CanMoveForward method operates correctly but it depends upon the three properties whose values are determined by hardware. By adding expectations to the properties we are able to test the operation of CanMoveForward by calling the method of the mock object.

[Test]
public void LanderCanMoveIfBatteryChargedMotorOKAndNotBlocked()
{
    Mock<MarsLander> mockMarsLander = new Mock<MarsLander>();
    mockMarsLander.Setup(m => m.BatteryChargePercentage).Returns(25);
    mockMarsLander.Setup(m => m.PathBlocked).Returns(false);
    mockMarsLander.Setup(m => m.MotorStatus).Returns("OK");

    Assert.IsTrue(mockMarsLander.Object.CanMoveForward());
}

Using CallBase

The manner in which partial mock objects are constructed means that the behaviour of members defined in base classes may not be as you would expect. You may expect that if you exclude the expectation on the MotorStatus property that calling it would yield the result, "OK". However, the standard result of a call to a base method of a partial mock is to return the default value for the expected data type. In the case of strings, the result of the call will be null.

We can see this by running the following test. If the MotorStatus method returned "OK", the test would pass. However, the method returns null so the test fails.

[Test]
public void LanderCanMoveIfBatteryChargedMotorOKAndNotBlocked()
{
    Mock<MarsLander> mockMarsLander = new Mock<MarsLander>();
    mockMarsLander.Setup(m => m.BatteryChargePercentage).Returns(25);
    mockMarsLander.Setup(m => m.PathBlocked).Returns(false);

    Assert.IsTrue(mockMarsLander.Object.CanMoveForward());
}

We can instruct mock objects to implement the functionality from base classes by setting the CallBase property of the mock to true. The updated test with this property set passes:

[Test]
public void LanderCanMoveIfBatteryChargedMotorOKAndNotBlocked()
{
    Mock<MarsLander> mockMarsLander = new Mock<MarsLander>();
    mockMarsLander.CallBase = true;
    mockMarsLander.Setup(m => m.BatteryChargePercentage).Returns(25);
    mockMarsLander.Setup(m => m.PathBlocked).Returns(false);

    Assert.IsTrue(mockMarsLander.Object.CanMoveForward());
}
9 February 2012