C# Test Mocking Frameworks


There are a number of mocking frameworks available to .NET programmers, these include:

  1. Moq
  2. Rhino Mocks
  3. NSubstitute
  4. FakeItEasy
  5. Microsoft Fakes

All support the generation of standins for abstract classes, interfaces and allow the interception of virtual methods and functions. I believe a lot of them are based on the same technology.

One thing to note is that none of them work with WinRT due to it not having any of the classes from the System.Reflection.Emit namespace. There does appear to be third party support for WinRT from Telerik and there is also an open source project named MoqRT. The main requirements are:

  1. Simple to learn
  2. Feature rich

When comparing the frameworks it seems that it is the API that is the key to making a selection. Below is the code taken from the blog http://weareadaptive.com/blog/2014/09/30/why-nsubstitute/, which I believe illustrates that NSubstitute is simplest to use as it relies less on lambda expressions:

Mock Setup

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// NSubstitute
var quoteService = Substitute.For<IQuoteService>();
quoteService.SendQuote(Arg.Any<QuoteRequest>())
            .Returns(Task.FromResult(new QuoteRequestResult()));
 
// Moq
var quoteServiceMock = new Mock<IQuoteService>();
quoteServiceMock.Setup(s => s.SendQuote(It.IsAny<QuoteRequest>()))
                .Returns(Task.FromResult(new QuoteRequestResult()));
 
// Fake it easy
quoteService = A.Fake<IQuoteService>();
A.CallTo(() => quoteService.SendQuote(A<QuoteRequest>._))
 .Returns(Task.FromResult(new QuoteRequestResult()));
// NSubstitute
var quoteService = Substitute.For<IQuoteService>();
quoteService.SendQuote(Arg.Any<QuoteRequest>())
            .Returns(Task.FromResult(new QuoteRequestResult()));

// Moq
var quoteServiceMock = new Mock<IQuoteService>();
quoteServiceMock.Setup(s => s.SendQuote(It.IsAny<QuoteRequest>()))
                .Returns(Task.FromResult(new QuoteRequestResult()));

// Fake it easy
quoteService = A.Fake<IQuoteService>();
A.CallTo(() => quoteService.SendQuote(A<QuoteRequest>._))
 .Returns(Task.FromResult(new QuoteRequestResult()));

Assertions/Verification

1
2
3
4
5
6
7
8
9
// NSubstitute
quoteService.Received().SendQuote(Arg.Any<QuoteRequest>());
 
// Moq
quoteServiceMock.Verify(q => q.SendQuote(It.IsAny<QuoteRequest>()));
 
// Fake it easy
A.CallTo(() => quoteService.SendQuote(A<QuoteRequest>._))
 .MustHaveHappened();
// NSubstitute
quoteService.Received().SendQuote(Arg.Any<QuoteRequest>());

// Moq
quoteServiceMock.Verify(q => q.SendQuote(It.IsAny<QuoteRequest>()));

// Fake it easy
A.CallTo(() => quoteService.SendQuote(A<QuoteRequest>._))
 .MustHaveHappened();

Number of calls

1
2
3
4
5
6
7
8
9
// NSubstitute
quoteService.Received(1).SendQuote(Arg.Any<QuoteRequest>());
 
// Moq
quoteServiceMock.Verify(q => q.SendQuote(It.IsAny<QuoteRequest>()), Times.Once);
 
// Fake it easy
A.CallTo(() => quoteService.SendQuote(A<QuoteRequest>._))
 .MustHaveHappened(Repeated.Exactly.Once);
// NSubstitute
quoteService.Received(1).SendQuote(Arg.Any<QuoteRequest>());

// Moq
quoteServiceMock.Verify(q => q.SendQuote(It.IsAny<QuoteRequest>()), Times.Once);

// Fake it easy
A.CallTo(() => quoteService.SendQuote(A<QuoteRequest>._))
 .MustHaveHappened(Repeated.Exactly.Once);

Multiple results

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// NSubstitute
quoteService
    .SendQuote(Arg.Any<QuoteRequest>())
    .Returns(
      Task.FromResult(new QuoteRequestResult()),
      Task.Run(() => { throw new Exception(); }));
 
// Moq
quoteServiceMock
    .Setup(s => s.SendQuote(It.IsAny<QuoteRequest>()))
    .Returns(new Queue<Task<QuoteRequest>(new[]
    {
        Task.FromResult(new QuoteRequestResult()),
          Task.Run(() => { throw new Exception(); }
    }).Dequeue); // Note this is not native support, which is why we need a queue
 
// Fake it easy
A.CallTo(() => quoteService.SendQuote(A<QuoteRequest>._)
 .ReturnsNextFromSequence(
    Task.FromResult(new QuoteRequestResult()),
    Task.Run(() => { throw new Exception(); })) ;
// NSubstitute
quoteService
    .SendQuote(Arg.Any<QuoteRequest>())
    .Returns(
      Task.FromResult(new QuoteRequestResult()),
      Task.Run(() => { throw new Exception(); }));

// Moq
quoteServiceMock
    .Setup(s => s.SendQuote(It.IsAny<QuoteRequest>()))
    .Returns(new Queue<Task<QuoteRequest>(new[]
    {
        Task.FromResult(new QuoteRequestResult()),
          Task.Run(() => { throw new Exception(); }
    }).Dequeue); // Note this is not native support, which is why we need a queue

// Fake it easy
A.CallTo(() => quoteService.SendQuote(A<QuoteRequest>._)
 .ReturnsNextFromSequence(
    Task.FromResult(new QuoteRequestResult()),
    Task.Run(() => { throw new Exception(); })) ;

Here is another supporter of NSubstitute https://www.stevefenton.co.uk/2014/12/nsubstitute-vs-moq-vs-fakeiteasy-vs-rhino/.

Conclusion

Given that we also have a fair amount of unit tests based on NSubstitute and none of the others offer significant advantages, it seems obvious to continue using NSubstitute given its simpler API.

–EOF (The Ultimate Computing & Technology Blog) —

GD Star Rating
loading...
568 words
Last Post: C# Test Frameworks Comparisons
Next Post: How to Customize Search Engine for WordPress?

The Permanent URL is: C# Test Mocking Frameworks

Leave a Reply