
It’s now been a few months since the GDPR-drama and data-harvesting around Moq (Stop using Moq as a guinea pig to get feedback on and develop SponsorLink ) happened - and the only conclusion that remains is: please migrate away from Moq, as quickly and efficiently as possible.
Migrations
At the time of the drama, regex scripts and manual migrations were quickly recommended to get away from Moq, which sometimes worked more and sometimes less well. However, the larger the code base, the more complex the migration - and the more investment is required to migrate to NSubstitute, for example.
NSubstitute is also the project that has now taken over from Moq as the most popular mocking framework. Please support that project.
GitHub Copilot Chat
The effort of migrating from Moq to NSubstitute can now be significantly reduced thanks to GitHub Copilot Chat. You no longer need regex scripts or manual adjustments - instead, you can use the GitHub Copilot Chat to automate the migration. Automate at least file-by-file, because that’s all the GitHub Copilot Chat currently supports.
Sample
I have several hundred files in an existing application that I was able to migrate successfully in just a few steps; for example, this test file:
1public class AccountActivateControllerTests
2{
3 private readonly Mock<IEventEngineCore> _eventEngineMoq = new();
4 private readonly Mock<IPortalRouter> _prMock = new();
5 private readonly Mock<IIdentityContextAccessor> _icMoq = new();
6 private readonly AccountActivateController _controller;
7
8 public AccountActivateControllerTests()
9 {
10 _controller = new AccountActivateController(
11 _eventEngineMoq.Object, _icMoq.Object, _prMock.Object);
12 }
13
14 [Fact]
15 public void Activate_GET_Without_Passed_ActivationKey()
16 {
17 // setup
18 _icMoq.Setup(x => x.GetUserIdOrThrow()).Returns(new UserId(1));
19
20 // arrange
21 AccountActivateController controller = _controller;
22
23 // act
24 IActionResult activateResult = controller.Activate(key: null);
25 ViewResult viewResult = Assert.IsAssignableFrom<ViewResult>(activateResult);
26
27 // assert
28 viewResult.ViewName.Should().Be("~/Areas/Account/Views/Account/Activate.cshtml");
29
30 // verify
31 _eventEngineMoq
32 .Verify(ed =>
33 ed.Send(It.IsAny<UserAccountTryActivateByKeyCommand>(), CancellationToken.None),
34 Times.Never);
35 }
I selected this code in the VS editor and prompted convert it from moq to NSubstitute in the Copilot Chat. A few seconds later, GitHub Copilot replaced all moq snippets with NSubstitute actions:
1public class AccountActivateControllerTests
2{
3 private readonly IEventEngineCore _eventEngine = Substitute.For<IEventEngineCore>();
4 private readonly IPortalRouter _pr = Substitute.For<IPortalRouter>();
5 private readonly IIdentityContextAccessor _ic = Substitute.For<IIdentityContextAccessor>();
6 private readonly AccountActivateController _controller;
7
8 public AccountActivateControllerTests()
9 {
10 _controller = new AccountActivateController(_eventEngine, _ic, _pr);
11 }
12
13 [Fact]
14 public void Activate_GET_Without_Passed_ActivationKey()
15 {
16 // setup
17 _ic.GetUserIdOrThrow().Returns(new UserId(1));
18
19 // arrange
20 AccountActivateController controller = _controller;
21
22 // act
23 IActionResult activateResult = controller.Activate(key: null);
24 ViewResult viewResult = Assert.IsAssignableFrom<ViewResult>(activateResult);
25
26 // assert
27 viewResult.ViewName.Should().Be("~/Areas/Account/Views/Account/Activate.cshtml");
28
29 // verify
30 _eventEngine
31 .DidNotReceive()
32 .Send(Arg.Any<UserAccountTryActivateByKeyCommand>(), CancellationToken.None);
33 }
GitHub Copilot is simply brilliant! Goodbye Moq. Hello NSubstitute ♥

Comments