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…
|
|
Our Car Repository Interface…
|
|
Given a CarService that uses an ICarRepository to return a list of cars then we could set up the test like so…
|
|
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.
|
|
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.