There are quite a few different mocking libraries in .NET. Moq and NSubstitute seem to be by far the main ones I hear that developers use. I've used both of these in different projects, and really like them both. Whilst my preference leans towards NSubstitute, I'd be happy using either. Out of interest, I posted a Twitter poll to see what other people preferred, and the results and replies were really interesting!...
What's your favourite mocking library for .NET and why? (reply for 'other' - Twitter didn't allow enough poll options)
— Dan Clarke (@dracan) August 8, 2020
The winner of the poll is clear - but interestingly, a lot of the replies indicated that they used Moq just because it was the most well known / used, and they hadn't tried anything else. There was certainly a lot of love for NSubstitute in the replies, commenting that the API is much cleaner.
I thought it would be interesting to compare some of the leading libraries like for like. So I picked the top three in the poll - namely, Moq, NSubstitute, and FakeItEasy. And I'll go through some code snippets for some of the more common requirements of a mocking library. Note that I can't possibly cover every thing in this blog post, but I'll focus on the features I find myself mostly using.
But first, what does a mocking library actually do?...
When writing a test, quite often you want to only test one particular class and method. But that method might call a dependency that calls into a database, or calls an external service. When writing an integration test, you may want to include those dependencies in your your test - perhaps using a real database span up in Docker, or an in-memory database. But what if you're only writing a unit-test (or the integration can't simulate a particular dependency)? How do you call the method you want to test, without it calling into the dependency and therefore making that database call?
Quite often in .NET codebases, you'll quite often see classes implement an interface - especially those which call into databases or make external API/service calls. For example, you might have a class called EFStockChecker
which has Entity Framework code that talks to a database to check stock level. This contains implementation details - ie. it uses the Entity Framework library. This might then implement an interface called IStockChecker
.
It is this interface that the rest of the codebase ideally should use - not the concrete type (implementation). The key point here is that the interface has no concept of Entity Framework, or whatever database technology we might be using. All it does is describe the intent. This is known as dependency inversion. When programming in this manor, your business logic isn't concerned with the implementation details of its dependencies. It also means that those dependences are really easy to replace with another implementation when testing.
Let's continue with the IStockChecker
example...
interface IStockChecker
{
bool IsProductInStock(string sku);
}
Nothing in the above interface indicates a database or database technology. It's just about the requirement, not how that requirement is fulfilled.
Then I might have some code in my business logic that does this...
public class OrderHandler
{
private readonly IStockChecker _stockChecker;
private readonly IOrderRepository _orderRepository;
public OrderHandler(IStockChecker stockChecker, IOrderRepository orderRepository)
{
_stockChecker = stockChecker;
_orderRepository = orderRepository;
}
public void ProcessOrder(string sku)
{
if (_stockChecker.IsProductInStock(sku))
{
_orderRepository.Create(...);
...
}
}
}
Because this code only knows about abstractions (ie. the interfaces), it's easy to run this code without using the production implementation of those interfaces. I could just create another implementations just for the test that implements those interfaces, but doesn't call the database. These test implementations are known as 'stubs'.
A mocking library allows you to simulate an interface or abstract type's implementation. You instantiate a 'mock' object of the interface, and tell that mock object what it should return if a method/property is called against that mock. You can also assert that a method/property was or wasn't called.
Some people prefer sticking to stubs over mocking libraries, but I personally prefer to avoid creating additional classes when a mocking library can do it for us. A mocking library also adds additional functionality, like as mentioned above - being able to assert/verify that a mocked method was called. You could obviously implement this yourself in your test implementation - but a mocking library can do this for you, so why reinvent the wheel?
Let's start with a very simple scenario. Imagine we're testing the above-mentioned ProcessOrder
method. Two interfaces are injected into the constructor. The implementation of both of them call out into a database or API (but we don't care about the data source or implementation), as we're not testing this. We only care about the logic in our ProcessOrder
method. Eg. How does our ProcessOrder
handle the having stock vs being out of stock.
Below is an example test to ensure that an order isn't created if there's not enough stock (using the Moq mocking library)...
[Fact]
public void GivenInsufficientStock_DoNotCreateOrder()
{
// Arrange
var mockStockChecker = new Mock<IStockChecker>();
var mockOrderRepository = new Mock<IOrderRepository>();
mockStockChecker.Setup(x => x.IsProductInStock()).Returns(false);
var sut = new OrderHandler(mockStockChecker.Object, mockOrderRepository.Object);
// Act
sut.ProcessOrder();
// Assert
mockOrderRepository.Verify(x => x.CreateOrder(It.IsAny<int>()), Times.Never);
}
As you can see, the dependencies are mocked out. The real implementation would have called out to a database, but the class we're testing doesn't know or care about this - it just cares that whatever "IsProductInStock" is, we get a boolean back. It doesn't care where that comes from, as that's not it's responsibility. What is it's responsibility is that if IsProductInStock
returns true, the class we're testing will execute ProcessOrder
. And likewise, if it returns false, it does not execute ProcessOrder
.
The above example shows how simple it is to tell the mock object to return false
if IsProductInStock
is called. This bit is just like a stub, but created for you by the mocking library.
You can also see how we can leverage the mock to verify that CreateOrder
was or wasn't called. This bit is like a 'spy', but again, done for you by the mocking library.
(for a description of the different types of test-doubles - eg. dummies, fakes, stubs, spies, mocks - Martin Fowler has a post with a short description of each).
In fact, on the NSubstitute homepage, they even try to move away from these specific definitions, and state: "Mock, stub, fake, spy, test double? Strict or loose? Nah, just substitute for the type you need!".
Okay, now we know what a mocking library does - let's move onto some syntax comparisons...
Let's start with how we create a mock, then declare a return value for a method or property in a mocked object...
// Moq
var mockStockChecker = new Mock<IStockChecker>();
mockStockChecker.Setup(x => x.IsProductInStock()).Returns(true);
var sut = new TheClassIAmTesting(mockStockChecker.Object);
sut.DoSomething();
// NSubstitute
var mockStockChecker = Substitute.For<IStockChecker>();
mockStockChecker.IsProductInStock().Returns(true);
var sut = new TheClassIAmTesting(mockStockChecker);
sut.DoSomething();
// FakeItEasy
var mockStockChecker = A.Fake<IStockChecker>();
A.CallTo(() => mockStockChecker.IsProductInStock("")).Returns(true);
var sut = new TheClassIAmTesting(mockStockChecker);
sut.DoSomething();
NSubstitute certainly seems the cleanest here, not requiring .Object
or a .Setup
call and lambda. Note that Moq also has another syntax, where you don't need to use .Object
to get at the mocked object, but if you do this - you have the inverse problem, where you have to do Mock.Get(myMock)
to do any setup.
Moving forward, I'll omit the mock instantiation and the SUT call for brevity.
What about if your method takes parameters? Eg, we know our IsProductInStock
method does take a 'sku' parameter...
// Moq
mockStockChecker.Setup(x => x.IsProductInStock("banana")).Returns(false);
// NSubstitute
mockStockChecker.IsProductInStock("apple").Returns(true);
// FakeItEasy
A.CallTo(() => mockStockChecker.IsProductInStock("orange")).Returns(true);
This is very similar to the previous example - you just specify the parameter value when setting it up.
And what if your method takes a parameter, but you don't care what values are passed to it by the code you're testing?...
// Moq
mockStockChecker.Setup(x => x.IsProductInStock(It.IsAny<string>())).Returns(true);
// NSubstitute
mockStockChecker.IsProductInStock(Arg.Any<string>()).Returns(true);
// Or NSubstitute can also do this to specify that all arguments can be ignored
mockStockChecker.IsProductInStock(default).ReturnsForAnyArgs(true);
// FakeItEasy
A.CallTo(() => mockStockChecker.IsProductInStock(A<string>.Ignored))).Returns(true);
They all have similar syntax here. Moq uses It.IsAny<>()
syntax, NSubstitute uses Arg.Any<>()
, and FakeItEasy uses A<string>.Ignored
. In NSubstitute, you can also use ReturnsForAnyArgs
and the parameters will be ignored. In the above example, I've used the default
keyword when doing this to make it more clear that these values are ignored - I could have put "", or any other value, but I think using default
makes it more clear.
Quite often you want to have tests testing how your code handles a dependency throwing an exception. Mocks allow you to simulate exceptions being thrown...
// Moq
mockStockChecker.Setup(x => x.IsProductInStockAsync("")).Throws(new NullReferenceException());
// NSubstitute
mockStockChecker.IsProductInStock("").Throws(new NullReferenceException());
// FakeItEasy
A.CallTo(() => mockStockChecker.IsProductInStock("").Throws(new NullReferenceException());
All of these are very similar to their Returns
counterpart. Just replacing Returns
with Throws
.
Another really useful feature of mocking libraries is that you can spy on whether a mocked method was called or not. We saw an example of this in the GivenInsufficientStock_DoNotCreateOrder
code snippet earlier in this post, where we verified that CreateOrder
wasn't called when there was insufficient stock.
// Moq
mockOrderRepository.Verify(x => x.CreateOrder()); // Defaults to Times.AtLeastOnce
mockOrderRepository.Verify(x => x.CreateOrder(), Times.Never);
mockOrderRepository.Verify(x => x.CreateOrder(), Times.Once);
mockOrderRepository.Verify(x => x.CreateOrder(), Times.Exactly(2));
mockOrderRepository.Verify(x => x.CreateOrder(), Times.Exactly(3));
// NSubstitute
mockOrderRepository.Received().CreateOrder();
mockOrderRepository.DidNotReceive().CreateOrder();
mockOrderRepository.Received(1).CreateOrder();
mockOrderRepository.Received(2).CreateOrder();
mockOrderRepository.Received(3).CreateOrder();
// FakeItEasy
A.CallTo(() => mockOrderRepository.CreateOrder()).MustHaveHappened();
A.CallTo(() => mockOrderRepository.CreateOrder()).MustNotHaveHappened();
A.CallTo(() => mockOrderRepository.CreateOrder()).MustHaveHappenedOnceExactly();
A.CallTo(() => mockOrderRepository.CreateOrder()).MustHaveHappenedTwiceExactly();
A.CallTo(() => mockOrderRepository.CreateOrder()).MustHaveHappened(3, Times.Exactly);
I've included a few examples above showing how to check for different numbers of calls to a mocked method. This particular method I've verifying has no parameters, but all the libraries support verifying the a call was made with specific parameter values, or any parameter values.
I certainly haven't touched on all the functionalities that exist in mocking libraries - but rather focused on the features I tend to mostly use. There is plenty of other functionality - eg. working with events, verifying the order of method calls, etc, etc. If there are any comparisons or examples you feel really belong in this post, please do let me know.
The aim of this post isn't to say one library is better than another, as when it comes down to it, they all pretty much do the same thing. The purpose of this post is just to provide a side-by-side comparison of some of the syntax, to hopefully give the you a feel of what mock creation and setup looks like across these different libraries.