How to migrate from Moq to NSubstitute

Seamless Migration from Moq to NSubstitute

Alexander Wichmann Carlsen
ITNEXT

--

Table of contents

Basic Migration Steps:

Step 1: Install NSubstitute Package

Begin by installing the NSubstitute NuGet package into your project. You can do this via the NuGet Package Manager Console or the Visual Studio NuGet Package Manager.

Install-Package NSubstitute

Step 2: Replace Moq Imports

Update your test classes to use the NSubstitute namespace instead of Moq:

using NSubstitute;
// using Moq; (Remove this line)

Step 3: Creating Mocks

NSubstitute provides a Substitute class to create substitutes (mocks) for your classes and interfaces. Replace your Moq mock setup with NSubstitute syntax:

Moq:

var mockService = new Mock<IService>();
mockService.Setup(s => s.Method()).Returns(result);
mockService.Setup(s => s.MethodAsync()).ReturnsAsync(result);

NSubstitute:

var mockService = Substitute.For<IService>();
mockService.Method().Returns(result);

// Return Task.FromResult when using async methods
mockService.MethodAsync().Returns(Task.FromResult(result));

Step 4: Verifying Behavior

Transitioning from Moq’s .Verify() to NSubstitute's .Received() is straightforward:

Moq:

mockService.Verify(s => s.Method(), Times.Once);

NSubstitute:

mockService.Received(1).Method();

Advanced Concepts:

Arg and ReturnsForAnyArgs

NSubstitute provides Arg to handle argument matching and ReturnsForAnyArgs to define default return values:

mockService.Method(Arg.Any<int>()).ReturnsForAnyArgs(result);

Arg and Returns

Like above, you can also return results for specific args.

mockService.Method(Arg.Is<int>(1)).Returns(result);

When..Do

NSubstitute’s When..Do allows you to customize behavior based on arguments:

mockService
.When(m => m.Method(Arg.Is<int>(1))
.Do(x => CalculateResult((int)x[0]));

When..Do per argument callbacks

You can even do things for each time a mock is called…


var calls = new List<string>();
var counter = 0;

mockService
.When(m => m.Method(Arg.Any<int>()))
.Do(
Callback.First(x => calls.Add("1"))
.Then(x => calls.Add("2"))
.Then(x => calls.Add("3"))
.ThenKeepDoing(x => calls.Add("+"))
.AndAlways(x => counter++)
);

Partial Substitutes

Create partial substitutes for classes with virtual and non-virtual members:

var partialService = Substitute.ForPartsOf<MyService>();
partialService.Method().Returns(result);

Migration with Find/Replace

Dont forget to use Regex searching…

Using

  • Find: using Moq;
  • Replace: using NSubstitute;

Instance

  • Find: new Mock<(.+?)>\((.*?)\)
  • Replace: Substitute.For<$1>($2)

Instance

  • Find: \bMock<(.+?)>
  • Replace: $1

Setup

  • Find: (?<!\.)\b(\w+)(\s\n\s*)?\.Setup(Get)?\((\w+) => \4(\.?.+?)\)(?=\.R|\s\n)
  • Replace: $1$5
  • Find: \.Get<(.+?)>\(\)\.Setup\((\w+) => \2(\.?.+?)\)(?=\.R|\s\n)
  • Replace: .Get<$1>()$3
  • Find: \.Get<(.+?)>\(\)\.SetupSequence?\((\w+) => \3(\.?.+?)\)(?=\.R|\s\n)
  • Replace: .Get<$1>()$3
  • Find: (?<!\.)\b(\w+)(\s\n\s*)?\.SetupSequence?\((\w+) => \3(\.?.+?)\)(?=\.R|\s\n)
  • Replace: $1$4
  • Find: \.Get<(.+?)>\(\)\.SetupSequence?\((\w+) => \2(\.?.+?)(\)(?!\)))
  • Replace: .Get<$1>()$3

Verify

  • Find: (?<!\.)\b(\w+)\.Verify\((\w+) => \2(.+?), Times\.(Once(\(\))?|Exactly\((?<times>\d+)\))\)
  • Replace: $1.Received(${times})$3
  • Find: (?<!\.)\b(\w+)\.Verify\((\w+) => \2(.+?), Times\.Never\)
  • Replace: $1.DidNotReceive()$3

Throw

  • Find: (?<!\.)\b(\w+)(\s\n\s*)?\.Setup\(((\w+) => \4(\..?.+?)\))\)\s*\n*\.Throws
  • Replace: $1.When($3).Throw

Arg

  • Find: It.IsAny
  • Replace: Arg.Any
  • Find: It.Is
  • Replace: Arg.Is

Resources

The NSubstitute has great documentation as well, you can find it here.

https://nsubstitute.github.io/help

--

--

Writer for

I am a developer, Full-Stack enthusiast, Vue aficionado, Azure ninja, Microservice builder.