DEV Community

Cover image for Moq vs NSubstitute - Who is the winner?
Andres Lozada Mosto for Cloud(x);

Posted on • Updated on

Moq vs NSubstitute - Who is the winner?

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>();
Enter fullscreen mode Exit fullscreen mode

NSubstitute

var mock = Substitute.For<IRepository>();
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

NSubstitute

// Simple properties
mock.Users.Returns(userList);

// Hierarchy
mockUser.Address.Street.Returns(street);
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

NSubstitute

// - Arg.Any<int>())
// - Arg.Is<int>(i => i < 10))
Enter fullscreen mode Exit fullscreen mode

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");
Enter fullscreen mode Exit fullscreen mode

NSubstitute

mock.Add(Arg.Any<IUserModel>()).Returns(x => { return ((IUserModel)x[0]).Username == "Andres"; });
Enter fullscreen mode Exit fullscreen mode

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());
Enter fullscreen mode Exit fullscreen mode

NSubstitute

mock.SearchById(Arg.Any<int>()).Returns(userList.Skip(1).Take(1).First());
mock.SearchById(2).Returns(userList.First());
Enter fullscreen mode Exit fullscreen mode

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");
Enter fullscreen mode Exit fullscreen mode

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");
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

NSubstitute

mock.Search(Arg.Any<string>()).Returns(users1, users2, users3);
Enter fullscreen mode Exit fullscreen mode

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"));
Enter fullscreen mode Exit fullscreen mode

NSubstitute

mock.ActiveUsers().Returns(x => { throw new Exception(); });
mock.When(x => x.Save())
                .Do(x => { throw new Exception("msj"); });
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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

Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

NSubstitute

mock.AddUser<IUserModel>(Arg.Any<IUserModel>()).Returns(true);
mock.AddUser<IUserModel>(Arg.Any<UserModel2>()).Returns(false);
Enter fullscreen mode Exit fullscreen mode

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 🤙👇

Top comments (11)

Collapse
 
ianwebsteraci profile image
Ian Webster • Edited

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.

Collapse
 
andreslozadamosto profile image
Andres Lozada Mosto

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...

Collapse
 
dkarzhounikgdt profile image
Dzmitry Karzhounik

nice post

Collapse
 
countingquoll profile image
countingquoll

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);

Collapse
 
andreslozadamosto profile image
Andres Lozada Mosto

You are right!!
Next week I will update the post and mention you. Thanks!

Collapse
 
iamdorra profile image
Dorra BARTAGUIZ

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

Collapse
 
andreslozadamosto profile image
Andres Lozada Mosto

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 🙂

Collapse
 
adam_b profile image
Adam Braimah

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!

Collapse
 
jasonbock profile image
Jason Bock

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

Collapse
 
victoryarema profile image
Victor Yarema • Edited

The code one needs to write for callbacks testing in NSubstitute is just an unreadable and unmaintainable garbage. Especially when it comes to arguments.

Collapse
 
itsmash profile image
Mohammod Al Amin Ashik

If you add up mocking virtual protected method/property, logger mocking(with ILogger.Moq), and casting comparision, Moq will definitely be the winner.