In this article will compare two of most important mocking libraries for .Net (.Net Core and .Net Framework) NSubstitute and Moq.
What will we compare?
- Simplicity
- Readability
- Behaviours
The fight begins 💪
Mock creation
Moq
var mock = new Mock<IRepository>();
NSubstitute
var mock = Substitute.For<IRepository>();
Moq uses a more representative notation. Anyone, just reading that line can know that we are creating a mock object.
Winner: Moq
Mocking properties
Moq
// Simple properties
mock.Setup(foo => foo.Users).Returns(userList);
// Hierarchy
mockUser.Setup(foo => foo.Address.Street).Returns(street);
NSubstitute
// Simple properties
mock.Users.Returns(userList);
// Hierarchy
mockUser.Address.Street.Returns(street);
NSubstitue has a simpler interface to set up the returns.
Winner: NSubstitue
Mocking methods
Moq
// Without parameters
mock.Setup(x => x.ActiveUsers()).Returns(userList);
// Matching by value
mock.Setup(x => x.SearchById(1)).Returns(user);
// Matching by any value of the parameter type
mock.Setup(x => x.SearchById(It.IsAny<int>())).Returns(user);
// Matching by custom logic
mock.Setup(x => x.SearchById(It.Is<int>(i => i < 10))).Returns(user);
NSubstitute
// Without parameters
mock.ActiveUsers().Returns(userList);
// Matching by value
mock.SearchById(1).Returns(user);
// Matching by any value of the parameter type
mock.SearchById(Arg.Any<int>()).Returns(user);
// Matching by custom logic
mock.SearchById(Arg.Is<int>(i => i < 10)).Returns(user);
Same here, NSubstitute has a simpler interface to set up the returns of the methods mocked.
Winner: NSubstitue
Matching arguments
Moq
// - It.IsAny<int>())
// - It.IsInRange(0, 10, Range.Inclusive)
// - It.IsIn(Enumerable.Range(1, 5))
// - It.IsNotIn(Enumerable.Range(1, 5))
// - It.IsNotNull<string>())
// - It.IsRegex("abc"))
// - It.Is<int>(i => i < 10))
// - mock.Setup(x => x.Search(IsLarge())) //< custom
NSubstitute
// - Arg.Any<int>())
// - Arg.Is<int>(i => i < 10))
Moq provide us a lot more built-in options for matching arguments
Winner: Moq
Capturing parameter
Moq
mock.Setup(x => x.Add(It.IsAny<IUserModel>())).Returns((IUserModel user) => user.Username == "Andres");
NSubstitute
mock.Add(Arg.Any<IUserModel>()).Returns(x => { return ((IUserModel)x[0]).Username == "Andres"; });
With Moq, it is easier to get the arguments values before returning the mocked value and process them as needed.
Winner: Moq
Multiple matching
Moq
mock.Setup(x => x.SearchById(It.IsAny<int>())).Returns((int i) => userList.Skip(1).Take(1).First());
mock.Setup(x => x.SearchById(2)).Returns((int i) => userList.First());
NSubstitute
mock.SearchById(Arg.Any<int>()).Returns(userList.Skip(1).Take(1).First());
mock.SearchById(2).Returns(userList.First());
Both of them allow us to add as many match expressions that we need. If there is a conflict they will take the last expression that matches.
Winner: Tie
Callabacks
Moq
mock.Setup(x => x.SearchById(1))
.Callback((int x) => parameterValue = x)
.Returns(userList.First());
// Methods without return
mock.Setup(x => x.Save()).Callback(() => name = "aa");
// before and after
mock.Setup(x => x.SearchById(2))
.Callback<int>(x => parameterValue = x)
.Returns(userList.First())
.Callback<int>(x => name = "andres");
NSubstitute
mock.SearchById(1)
.ReturnsForAnyArgs(x =>
{
parameterValue = (int)x[0];
return userList.First();
});
// Methods without return
mock.When(x => x.Save())
.Do(x => name = "aa");
// before and after
mock.SearchById(2)
.ReturnsForAnyArgs(x =>
{
parameterValue = (int)x[0];
return userList.First();
})
.AndDoes(x => name = "andres");
In this case Moq* provides a more readable experience adding a function called “Callback” on the chain call.
Winner: Moq
Multi-returns
Moq
mock.SetupSequence(x => x.Users)
.Returns(users1)
.Returns(users2)
.Returns(users3);
NSubstitute
mock.Search(Arg.Any<string>()).Returns(users1, users2, users3);
Here both libraries are very similar right?.
Winner: Tie
Throwing Exceptions
Moq
mock.Setup(x => x.Save()).Throws<Exception>();
mock.Setup(x => x.Save()).Throws(new Exception("msj"));
NSubstitute
mock.ActiveUsers().Returns(x => { throw new Exception(); });
mock.When(x => x.Save())
.Do(x => { throw new Exception("msj"); });
Moq is easier to recognize that the function will throw an exception.
Winner: Moq
Verify
Moq
// Setter
mock.VerifySet(x => x.Users = users);
// Getter
mock.VerifyGet(x => x.Users);
// Methods with matchting
mock.Verify(x => x.Search(It.IsAny<string>()));
mock.Verify(x => x.Search("aaa"), Times.Never());
// Occurrences
// - Times.Never
// - Times.Once
// - Times.AtLeastOnce
// - Times.AtMost(2)
// - Times.Exactly(2)
NSubstitute
// Setter
mock.Received().Users;
// Getter
mock.Received().Users = users;
// Methods with matchting
mock.Received().Search("aa");
mock.DidNotReceive().Search("aaa");
mock.Received(2).Search("bb");
// Occurrences
// Nop
NSubsitute has a simple way to verify that a method was called but Moq has more options to test how many times the method was executed.
Winner: Moq
Matching Generic Type Arguments
Moq
mock.Setup(m => m.AddUser(It.IsAny<It.IsSubtype<IUserModel>>())).Returns(true);
mock.Setup(m => m.AddUser(It.IsAny<UserModel2>())).Returns(false);
NSubstitute
mock.AddUser<IUserModel>(Arg.Any<IUserModel>()).Returns(true);
mock.AddUser<IUserModel>(Arg.Any<UserModel2>()).Returns(false);
Again, both provide an easy way to mock Generic Methods
Winner: tie
Well, how is it going? Who is winning?
Let’s see the current score
Syntax | Moq | NSubstitute |
---|---|---|
Mock creation | ✅ | |
Mocking properties | ✅ | |
Mocking methods | ✅ | |
Matching arguments | ✅ | |
Multiple matching | tie | tie |
Callabacks | ✅ | |
Multi-returns | tie | tie |
Throwing Exceptions | ✅ | |
Verify | ✅ | |
Matching Generic Type Arguments | tie | tie |
Moq is the winner!! 😀 🎉
I really prefer Moq and I try to use it always but both are excellent options to use. Us, as developers, we should be able to work with both.
You can download the examples from my Github
https://github.com/andreslozadamosto/net-thoughts/tree/master/libraries/testing/MoqVsNSubstitute/MockingLibrariesExamples
Are you with me?
Do you prefer NSubstitue?
I forget to compare any behaviour?
Share your comments 🤙👇
Oldest comments (12)
Hello thanks for this post blog.
But I don't agree with some points.
To throw exceptions, I think that Nsubstitute is the winner because the syntaxe is
moq.Method().Throws();
instead of your suggestion
the example of Multi-returns is not the same, so we feel that the syntaxe of moq is better or equal to Nsubstitute one. But for the example :
mock.SetupSequence(x => x.Users)
.Returns(users1)
.Returns(users2)
.Returns(users3);
the best syntaxe of Nsubstitute would be
mock.Users.Returns(users1, users2, users3);
So for me Nsubstitute is better about multi-returns
Hi Dorra, do you have good points here
Let me check about the Throws...
Regarding Multi-Returns, in my opinion Moq has a more readable syntax, but is only my opinion and I'm very glad to hear that you have your own point of view 🙂
The code one needs to write for callbacks testing in NSubstitute is just an unreadable and unmaintainable garbage. Especially when it comes to arguments.
I think you forgot another area of syntax where NSubstitute is the clear winner: when referencing the mocked object, e.g. when it is being injected.
var mockedRepo = new Mock<IRepository>();
var sut = new MyClass(mockedRepo.Object);
vs
var mockedRepo = Substitute.For<IRepository>();
var sut = new MyClass(mockedRepo);
You are right!!
Next week I will update the post and mention you. Thanks!
nice post
If you add up mocking virtual protected method/property, logger mocking(with ILogger.Moq), and casting comparision, Moq will definitely be the winner.
Anyone visiting this post should carefully consider using Moq in light of this github.com/moq/moq/pull/1373 it seems the project maintainer feels that illicitly harvesting his users email addresses is a good money making idea.
Yep
The version 4.20.69 published 2 days ago he removed the reference to sponsor link package but the trust with the community ... Well you know...
This is suddenly even more pertinent with the controversy over the latest versions of Moq having SponsorLink attached - I think a lot of people will be looking at alternatives like NSubstitute and FakeItEasy!
FWIW I've written a mocking framework that's based on the source generator feature in C#. It's called Rocks - feel free to check it out and let me know what you think.
github.com/JasonBock/Rocks/
nuget.org/packages/Rocks
Some comments may only be visible to logged-in visitors. Sign in to view all comments.