Moq vs NSubstitute Code Comparisons

August 17, 2023#Software Development
Article
Author image.

Sarah Dutkiewicz, Senior Trainer

As you move from Moq to NSubstitute, you may wonder how they differ code-wise. In a recent lunch-n-learn discussion, Scott DePouw walked us through how the code differs between them, so let’s see his findings.

The code is available in our NimblePros/moq-to-nsubstitute-guide repository.

In this article:

Creating a mock widget

In Moq, your code to create a fake Widget() may look like this:

_mock.Setup(factory => factory.Create()).Returns(new Widget());

To create a fake Widget() in NSubstitute, the code will look like this:

_mock.Create().Returns(new Widget());

What if you are creating a widget asynchronously? Your Moq code may look like this:

_mock.Setup(client => client.GetAsync()).ReturnsAsync("Foo");

The NSubstitute code to create a widget asynchronously will look like this:

_mock.GetAsync().Returns("Foo");

Verifying method calls

Suppose you want to ensure that a method is called. These are some scenarios that you may want to check.

Verify a call was made

This is the code in Moq to verify that a call was made:

_mock.Verify(factory => factory.Create());

This is the equivalent in NSubstitute to verify that a call was made:

_mock.Received().Create();

Verify a call was made exactly once

If you want to verify that a call to a method was made exactly one time, this is how you do it in Moq:

_mock.Verify(factory => factory.Create(), Times.Once);

In NSubstitute, you specify the expected number of times a method was called as part of Received(). Here is how to check that a method was called exactly once with NSubstitute:

_mock.Received(1).Create();

Verify a call was never made

You may want to ensure that a call was never made, such as with an exceptional case. This is how you ensure a call was never made using Moq:

_mock.Verify(factory => factory.Create(), Times.Never);

This is how you ensure a call was never made using NSubstitute:

_mock.Received(0).Create();

Verify a call for a specific number of calls

What if you have a method that needs to be called a specific number of times? You can test for an exact number of calls - such as 5 times - using Moq like this:

_mock.Verify(factory => factory.Create(), Times.Exactly(5));

The way to test if a method was called 5 times in NSubstitute looks like this:

_mock.Received(5).Create();

Verify no other calls

If you want to verify that no other calls were made, you can do this in Moq:

_mock.VerifyNoOtherCalls();

There is no direct equivalent to VerifyNoOtherCalls() in NSubstitute. However, some folks have suggested looking into assertions on the substitute’s ReceivedCalls() results.

Verify async calls

If you need to verify that an asynchronous call was made, this is how you would do it in Moq:

_mock.Verify(client => client.GetAsync());

When verifying asynchronous calls with NSubstitute, you need to make sure to use the await keyword, like this:

await _mock.Received().GetAsync();

Setting up arguments in mocked method calls

Setting up arguments is common when testing with mocked methods.

With Moq, arguments can be specified with It.Is<T>() and It.IsAny<T>(), like this:

_mock.Setup(calc => calc.Add(It.IsAny<int>()));
_mock.Setup(calc => calc.Add(It.Is<int>(num => num % 2 == 0));

In NSubstitute, you use Arg.Any<T>() and Arg.Is<T>() to add arguments to a mocked method call, like this:

_mock.Add(Arg.Any<int>()).Returns(5);
_mock.Add(Arg.Is<int>(num => num % 2 == 0)).Returns(5);

Accessing a mock’s calls and arguments

If you want to access the calls and arguments, you can do this with both packages.

In Moq, calls are known as invocations. Arguments are tied to an invocation. The following code gets the arguments for the first invocation:

_mock.Invocations();
_mock.Invocations[0].Arguments;

In NSubstitute, calls are received calls. Arguments are tied to a call. The following code gets the arguments for the first call using NSubstitute:

_mock.ReceivedCalls();
_mock.ReceivedCalls().First().GetArguments();

Setting up exceptions

Testing isn’t just about the happy path. This is how you handle testing with exceptions using Moq:

_mock.Setup(factory => factory.Create()).Throws(new Exception());
_mock.Create().Throws(new Exception());

You can also test with exceptions using NSubstitute:

_mock.Setup(client => client.GetAsync()).ThrowsAsync(new Exception());
_mock.GetAsync().ThrowsAsync(new Exception());

Conclusion

These are just some of the many things that you can do in Moq and NSubstitute. If you are considering migrating from Moq to NSubstitute, we also recommend checking out Ardalis’ post on Porting Moq to NSubstitute. If you have a project involving this that could use an extra set of hands on, contact us!


Copyright © 2024 NimblePros - All Rights Reserved