Back to Blog

DepenMock v3: Pick Your Mocking Framework

April 26, 2026

Featured image for DepenMock v3: Pick Your Mocking Framework

Some features ship because they're urgent. Others ship because you finally got the design right. The v3 release of DepenMock is firmly in the second camp.

When I first started building DepenMock, I had two long-term goals in mind: abstract the testing framework (so you could use NUnit, MSTest, or xUnit) and abstract the mocking framework (so you weren't locked into Moq). The testing framework side came together early, that's been in place since the beginning. The mocking framework side took three attempts and a couple of hard lessons before it landed correctly.

With v3.0 and v3.1, that second goal is done. DepenMock now supports Moq, NSubstitute, and FakeItEasy; and you can swap between them with a single line of code.


A Quick Recap (New to DepenMock?)

DepenMock is a C# testing library that eliminates the boilerplate of setting up mocked dependencies in unit tests. Instead of manually constructing every mock and wiring them into your system under test, you inherit from a base class and get all of that for free.

public class OrderServiceTests : BaseTestByAbstraction<OrderService, IOrderService>
{
    public OrderServiceTests() : base(new MoqMockFactory()) { }

    [Fact]
    public void ProcessOrder_ValidRequest_SavesOrder()
    {
        // Arrange
        var order = Container.Create<Order>();
        Container.ResolveMock<IOrderRepository>().AsMoq()
            .Setup(x => x.Save(It.IsAny<Order>()));
        var sut = ResolveSut();

        // Act
        sut.ProcessOrder(order);

        // Assert
        Container.ResolveMock<IOrderRepository>().AsMoq()
            .Verify(x => x.Save(order), Times.Once);
    }
}

If this is the first time you're hearing about DepenMock, check out the intro post for a fuller walkthrough. The rest of this post assumes you're familiar with the basics.


How We Got Here: Three Attempts at the Right Abstraction

Attempt One: Scrapped

The first attempt at abstracting the mocking framework never shipped. The design felt off early, and rather than push it through, I scrapped it. No concrete artifacts to show here, just the lesson that the right abstraction wasn't obvious.

Attempt Two: v2.0.0 - The Foundation

v2.0.0 introduced the IMock<T> and IMockFactory interfaces, which gave DepenMock a mocking-framework-agnostic core for the first time. Moq moved out of the core package and into its own DepenMock.Moq package. ResolveMock<T>() started returning IMock<T> instead of Moq's Mock<T> directly.

This was real progress, but when I tried to wire up a second mocking framework on top of the v2 design, it became clear the abstraction still wasn't quite right. The seams were in the wrong places.

Attempt Three: v3.0.0 - Getting It Right

v3 redesigned how the mock factory is threaded through the base classes. Instead of the base classes managing factory creation internally, the factory is now passed explicitly to the constructor. That one shift made everything click, and suddenly adding NSubstitute (v3.0.0) and FakeItEasy (v3.1.0) was straightforward.


What's New in v3.0: NSubstitute Support

v3.0.0 ships a new DepenMock.NSubstitute package. If your team prefers NSubstitute's argument-style API, you can now use it with DepenMock without any other changes to how your tests are structured.

public class OrderServiceTests : BaseTestByAbstraction<OrderService, IOrderService>
{
    public OrderServiceTests() : base(new NSubstituteMockFactory()) { }

    [Fact]
    public void ProcessOrder_ValidRequest_SavesOrder()
    {
        // Arrange
        var order = Container.Create<Order>();
        var sut = ResolveSut();

        // Act
        sut.ProcessOrder(order);

        // Assert
        Container.ResolveMock<IOrderRepository>().AsNSubstitute()
            .Received(1).Save(order);
    }
}

The .AsNSubstitute() extension method unwraps the IMock<T> into NSubstitute's native substitute so you can use its full API; Received(), Returns(), Arg.Any<T>(), and everything else you're used to.

v3.0 Breaking Change: Explicit Mock Factory

The base classes no longer create a MoqMockFactory internally. You now pass the factory yourself. This is a one-line change, but it is a compile-time break โ€” see the migration guide below.


What's New in v3.1: FakeItEasy Support

v3.1.0 follows the same pattern with a new DepenMock.FakeItEasy package. If you're a FakeItEasy shop, here's what using it looks like:

public class OrderServiceTests : BaseTestByAbstraction<OrderService, IOrderService>
{
    public OrderServiceTests() : base(new FakeItEasyMockFactory()) { }

    [Fact]
    public void ProcessOrder_ValidRequest_SavesOrder()
    {
        // Arrange
        var order = Container.Create<Order>();
        var fakeRepo = Container.ResolveMock<IOrderRepository>().AsFake();
        var sut = ResolveSut();

        // Act
        sut.ProcessOrder(order);

        // Assert
        A.CallTo(() => fakeRepo.Save(order)).MustHaveHappenedOnceExactly();
    }
}

.AsFake() unwraps the IMock<T> into FakeItEasy's native fake, giving you access to A.CallTo(), MustHaveHappened*(), and the rest of FakeItEasy's API.


The Full Framework Matrix

Here's where DepenMock stands today across both axes, testing framework and mocking framework:

Package Testing Framework Mocking Framework
DepenMock.XUnit + DepenMock.Moq xUnit Moq
DepenMock.XUnit + DepenMock.NSubstitute xUnit NSubstitute
DepenMock.XUnit + DepenMock.FakeItEasy xUnit FakeItEasy
DepenMock.NUnit + DepenMock.Moq NUnit Moq
DepenMock.NUnit + DepenMock.NSubstitute NUnit NSubstitute
DepenMock.NUnit + DepenMock.FakeItEasy NUnit FakeItEasy
DepenMock.MSTest + DepenMock.Moq MSTest Moq
DepenMock.MSTest + DepenMock.NSubstitute MSTest NSubstitute
DepenMock.MSTest + DepenMock.FakeItEasy MSTest FakeItEasy

Mix and match however your team prefers.


Migrating to v3

If you're upgrading from v2, here's what you need to change.

1. Add your mocking framework package

If you're sticking with Moq, make sure you have a reference to DepenMock.Moq. For NSubstitute or FakeItEasy, add the corresponding package:

dotnet add package DepenMock.Moq
dotnet add package DepenMock.NSubstitute
dotnet add package DepenMock.FakeItEasy

2. Add a constructor to your test classes

Every test class that inherits from a DepenMock base class now needs to pass a mock factory to the base constructor. Pick the factory that matches your mocking framework:

// Before (v2.0.0) - no constructor needed
public class OrderServiceTests : BaseTestByAbstraction<OrderService, IOrderService>
{
    // tests...
}

// After (v3.0.0) - pass the factory explicitly
public class OrderServiceTests : BaseTestByAbstraction<OrderService, IOrderService>
{
    public OrderServiceTests() : base(new MoqMockFactory()) { }
    // tests...
}

The same applies to BaseTestByType<T> and any class that extends BaseTest directly. If you're on a large codebase, this is a global find-and-replace job โ€” but it only touches the constructor, nothing inside the tests themselves.

3. Update ResolveMock<T>() call sites (if upgrading from v1)

If you skipped v2 and are jumping straight from v1 to v3, you'll also need to add .AsMoq() wherever you call Moq APIs on a resolved mock:

// v1 style
Container.ResolveMock<IOrderRepository>()
    .Setup(x => x.Save(It.IsAny<Order>()));

// v3 style
Container.ResolveMock<IOrderRepository>().AsMoq()
    .Setup(x => x.Save(It.IsAny<Order>()));

Installing

Pick the combination that matches your stack:

# Core + your test framework
dotnet add package DepenMock
dotnet add package DepenMock.XUnit      # or .NUnit / .MSTest / .XUnit.V3

# Your mocking framework
dotnet add package DepenMock.Moq        # or .NSubstitute / .FakeItEasy

Wrapping Up

v3 isn't the flashiest release, but it's one of the most satisfying โ€” it closes out a goal that's been on the roadmap since the beginning. DepenMock now works the way I always intended it to: fully agnostic about both your testing framework and your mocking framework.

If you've been holding off on adopting DepenMock because you're a NSubstitute or FakeItEasy team, now's a good time to give it a try.

๐Ÿ‘‰ GitHub repo ยท NuGet packages


Happy testing!


Profile picture

Written by Shannon Stewart I am a software architect and engineer focused on Azure, C#, and AI. I write about real-world projects, cloud-native patterns, and building smarter systems with modern tools.

ยฉ 2026, Built with Gatsby