There are a number of mocking frameworks available to .NET programmers, these include:
- Moq
- Rhino Mocks
- NSubstitute
- FakeItEasy
- 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:
- Simple to learn
- 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) —
loading...
Last Post: C# Test Frameworks Comparisons
Next Post: How to Customize Search Engine for WordPress?