You mocking me?

In unit testing, a mock is an object that mimics the behavior of a real object. Mock objects are set up to perform a certain behavior allowing you to test very specific scenarios. They are used in place of real objects when the real object is impractical (or sometimes impossible) to incorporate into the unit test.

For an example of an impractical scenario, suppose you have a piece of code that interacts with a database. When testing this code, you don’t want to have to depend on the database as it could be slow, unavailable, or produce inconsistent results as its state changes over time. Instead, you could use a mock object to simulate the behavior of the database. The mock object would mimic the database’s interface and could be set up to return fixed values in response to method calls.

Mocking is a common practice in unit testing and is supported by various libraries and frameworks.

Using mock objects allows you to isolate the code under test, focus on its behavior, and ensure that your tests run quickly and consistently. We’ll be looking at this in this post.

Mocking Libraries

There are lots of mocking libraries available. To date I have used Moq, but as part of this unit testing review took a look at some of the others.

Library Notes
Moq Moq is the one I’ve used previously. It is still one of the most widely used mocking libraries for .NET. It has a very simple syntax, uses generics and lambda expressions and is easy to read and understand.
Rhino Mocks This is one of the older mocking libraries for .NET. It’s very feature-rich but has a slightly more complex syntax compared to Moq or NSubstitute. It’s less commonly used now but is still relevant, particularly in legacy codebases.
NSubstitute It is designed to have a friendly syntax and make the creation of mock objects as painless as possible.
FakeItEasy Released at around the same time as the other Moq and NSubstitute frameworks. It’s syntax and style is a blend of the two (NSubstitutes factory, the mocking of methods similar to Moq’s).
JustMock A commercial mocking tool, supporting mocking of non-virtual methods, sealed classes, static methods and classes, as well as non-public members and types.

I didn’t spend a huge amount of time evaluating each of the libraries. This site provides a good comparison of the libraries and the syntax differences.

I settled on NSubstitute. It is free and open source, has been going for 10+ years and still has an active community with regular updates. It’s syntax is well thought out and easy to read and understand.

NSubstitute in action

NSubstitute works by creating a mock object that implements the same interface or inherits from the same class as the real object you want to substitute. The mock object is then injected into the system under test, and you can specify its behaviour using a fluent syntax.

Here’s an example of how to use NSubstitute to create a mock object and specify its behaviour.

Assuming a crude Car Repository that returns a list of Cars…

1
2
3
4
5
6
public class Car
{ 
    public int Id { get; set; }
    public string Make { get; set; }
    public string Model { get; set; }
}

Our Car Repository Interface…

1
2
3
4
public interface ICarRepository
{
    List<Car> GetCars();
}

Given a CarService that uses an ICarRepository to return a list of cars then we could set up the test like so…

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public class CarServiceTests
{
    // Our system under test
    private readonly CarService _sut;

    // Create a mock object that implements the ICarRepository interface
    private readonly ICarRepository _carRepository = Substitute.For<ICarRepository>();

    public CarServiceTests()
    {
        _sut = new CarService(_carRepository);
    }

    [Fact]
    public void GetCars_ShouldReturnAListOfCars_WhenCarsExist()
    {
        // Arrange

        // Set up the behavior of the GetCars method to return a list of two cars
        var cars = new List<Car>
        {
            new Car { Id = 1, Make = "Honda", Model = "Accord" },
            new Car { Id = 2, Make = "Toyota", Model = "Camry" }
        };
        _carRepository.GetCars().Returns(cars);

        // Act - Call the GetCars method and retrieve the list of cars
        var retrievedCars = _carRepository.GetCars().Result.ToArray();

        // Assert
        // Verify that the GetCars method was called once
        _carRepository.Received(1).GetCars();

        // Assert that the retrieved list of cars contains two cars with the correct make and model
        retrievedCars.Should().HaveCount(2);
        retrievedCars.Should().Contain(c => c.Make == "Honda" && c.Model == "Accord");
        retrievedCars.Should().Contain(c => c.Make == "Toyota" && c.Model == "Camry");
    }
}

In this example, we create a mock object that implements the ICarRepository interface using the Substitute.For method. We then set up the behaviour of the GetCars method using the Returns method to specify that it should return a list of two cars when called.

Finally, we call the GetCars() method on the Service and verify that it was actually called using the Received method.

NSubstitute provides a rich set of features for specifying the behavior of mock objects, including support for property and event mocking, argument matching, and callbacks.

Mocking http calls

RichardSzalay.MockHttp is a library for mocking HttpClient instances in .NET.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
    // Arrange
    var mockHttp = new MockHttpMessageHandler();
    
    // Setup a respond for a specific request
    mockHttp.When("http://localhost/api/test")
    .Respond("application/json", "{ 'value' : 'ok'}"); // Respond with JSON
    
    // Use HttpClient with the mock handler here
    var httpClient = new HttpClient(mockHttp);
    var url = "http://localhost/api/test";
    
    // Act
    var response = await httpClient.GetStringAsync(url);
    
    // Assert
    response.Should().Be("{ 'value' : 'ok'}");

In this example, MockHttpMessageHandler is set up to return a specific JSON response when a GET request is made to the url “http://localhost/api/test”. It is then used to create a new HttpClient instance. When this client is used to send a request to the specified URL, it will receive the mock response set up earlier. You can set up different responses based on urls, with specific request parameters, form values, content or headers. It also uses the fluid syntax making it easy to read and consistent with the other syntax used by NSubstitute and FluidAssertions.