How to migrate from Moq to NSubstitute
Seamless Migration from Moq to NSubstitute
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.