Blogtronica

Thoughts, ramblings and insights

netronica.io

NSubstitute vs Moq vs FakeItEasy

I have decided to do a very subjective and unscientific comparison of the three biggest mocking frameworks, partly because it is interesting, and because it is good to occasionally re-evaluate the tools you're using, otherwise you're stuck with the same old ...

What do the majority of people use

Usage of NSubstitute vs Moq vs FakeItEasy Inferred from version downloads! not actual download data!

Unfortunately there aren't any long term nuget download statistics available, therefore I have opted for a very unscientific mapping of number of downloads per version, and graphed that by the release date. I suspect this method is the reason why all 3 seem to be in "decline" but that could be an artificial boost from re-downloads of old versions as plenty of old projects would be stuck with the version that was available when it was originally developed.

Now that we have all the disclaimers out of the way, we can start looking at the chart. In terms of absolute number of downloads Moq(8.5M) wins hands down, followed by NSubstitute (1.5M) and last is FakeItEasy (0.6M). But, looking at the download trends, Moq seems to be suffering a rapid decline in popularity compared to the other two (who might actually be growing, see above disclaimer)

Comparison.

Let's start with the old favourite.

Moq

A sample moq

var somethingMock = new Mock<ISomething>();  
somethingMock.Setup(s => s.DoSomethingAsync(It.IsAny<int>())).ReturnsAsync("hello");  
var sut = new Something(somethingMock.Object);  
var result = await sut.MethodUnderTestAsync();  
Assert.AreEqual(result, "hello");  
somethingMock.Verify(e => e.DoSomethingAsync(It.IsAny<int>()), Times.AtLeastOnce);  

Pros:

  • Intuitive It.Is<T> argument matching syntax
  • The Setup and Verify methods make it clear which operations are provided

Cons:

  • A lot of typing to get a simple mock that returns something. mockSomeClass.Setup(mock => mock.DoSomething()).Returns("something");
  • Having to call .Object on the mock, in order to access the mocked object.
  • The setup and verify lines feel repetitive, and can be long.
  • Pulls in "Castle.Core" as a dependency. The other two have no nuget dependencies.
  • No .NET core support (yet)

NSubstitute

A sample NSubstitute

var somethingMock = Substitute.For<ISomething>();  
somethingMock.DoSomethingAsync(Arg.Any<int>()).Returns("hello");  
var sut = new Something(somethingMock);  
var result = await sut.MethodUnderTestAsync();  
Assert.AreEqual(result, "hello");  
await somethingMock.Received(1).DoSomethingAsync(Arg.Any<int>());  

Pros

  • Intuitive Arg.Any<int> argument matching syntax
  • Its use of extension methods do make setup, and verification methods a breeze!
  • .NET core support

Cons

  • Its use of extension methods on any T, can muddy things compared to the other two. And it can get even worse when combined with libraries that do the same something (e.g. fluentvalidation).
  • Because it uses extension methods, your tooling will complain if you don't await the call verification methods of async mocks await somethingMock.Received(1).DoSomethingAsync(Arg.Any<int>());
  • Because it uses extension methods, it is easy to mess up the call verification methods await somethingMock.DoSomethingAsync(Arg.Any<int>()).Received(1); luckily it throws an exception with some useful clues

FakeItEasy

A sample FakeItEasy

var somethingMock = A.Fake<ISomething>();  
A.CallTo(() => somethingMock.DoSomethingAsync(A<int>._)).Returns("hello");  
var sut = new Something(somethingMock);  
var result = await sut.MethodUnderTestAsync();  
Assert.AreEqual(result, "hello");  
A.CallTo(() => somethingMock.DoSomethingAsync(A<int>._)).MustHaveHappened();  

Pros:

  • Setting up the fake reads well var foo = A.Fake<Foo>();
  • Its CallTo lambda makes it clear which operations are provided for setup and verify

Cons:

  • A<int>.That The grammar nazi in me struggles with this use of the 'a' particle.
  • I find the fact that I have to pass a function lambda to set up fake return values and similarly to call verification methods quite unintuitive i.e. A.CallTo(() => somethingMock.DoSomethingAsync(A<int>._)).Returns("hello"); and A.CallTo(() => somethingMock.DoSomethingAsync(A<int>._)).MustHaveHappened();, at least compared to the other two
  • No .NET core support (yet)

Conclusions.

This is quite a tough call. All three are fairly descent, and let's face it, the differences are quite superficial. I think the purist in me likes how clean Moq is, but the easy to read English from FakeItEasy is nice and the liberal use of extension methods do make NSubstitute easy to get going - and fewer barriers to testing is a good thing, right?

Rather than calling a clear winner, I'll leave it here, as I have proved what I wanted to prove, and that is that I am not missing out by using my library of choice. Which if you're interested is nSubstitute.