NimbleMock: A Modern, Blazing-Fast Mocking Library for .NET (34x Faster Than Moq)

Published: (December 13, 2025 at 06:57 PM EST)
3 min read
Source: Dev.to

Source: Dev.to

Cover image for NimbleMock: A Modern, Blazing-Fast Mocking Library for .NET (34x Faster Than Moq)

Why I Built NimbleMock

Over the years, I’ve dealt with common mocking frustrations in enterprise .NET apps:

  • Verbose setups for large interfaces (mocking 20+ methods just to test one).
  • Performance hits from runtime proxies (Castle.DynamicProxy in Moq) — slow creation and verification in big test suites.
  • Static/sealed mocking hell — no native support without paid tools or wrappers.
  • Async and generics issues — unexpected null tasks or clunky type inference.
  • Brittle tests — mocks that pass locally but fail in production because they don’t match real API shapes.

Moq is battle‑tested, NSubstitute is clean and readable, but neither fully leverages modern .NET features like source generators for zero overhead.

NimbleMock fixes these with compile‑time magic: no runtime proxies, aggressive inlining, and stack allocation. Result? 34× faster mock creation and 3× faster verification than Moq, with zero allocations in typical scenarios.

Key Features

  • Partial mocks – only mock what you need; unmocked methods throw NotImplementedException for early detection.
  • Native static/sealed mocking – mock DateTime.Now, Environment, etc., directly.
  • First‑class async support – seamless for Task and ValueTask.
  • Generic type inference – full support for nested generics (e.g., EF Core IQueryable).
  • Fluent, chainable API – inspired by the best of NSubstitute and Moq.
  • Lie‑proofing – optional runtime validation against real staging APIs to catch outdated mock shapes.
  • Compile‑time analyzers – catch errors early (e.g., warn if you forget SetupAsync for async methods).

MIT‑licensed, open‑source, and ready for contributions!

Quick Start

Install via NuGet

dotnet add package NimbleMock

Basic example

using NimbleMock;

public interface IUserRepository
{
    User GetById(int id);
    Task SaveAsync(User user);
}

var mock = Mock.Of()
    .Setup(x => x.GetById(1), new User { Id = 1, Name = "Alice" })
    .SetupAsync(x => x.SaveAsync(default!), true)
    .Build();

var user = mock.Object.GetById(1); // Returns Alice

mock.Verify(x => x.GetById(1)).Once();

Partial mock (perfect for god‑interfaces)

var mock = Mock.Partial()
    .Only(x => x.GetData(1), expectedData)
    .Build();

// Unmocked methods throw for safety

Static mocking

var staticMock = Mock.Static()
    .Returns(d => d.Now, new DateTime(2025, 12, 25))
    .Build();

staticMock.Verify(d => d.Now).Once();

Generics example

public interface IRepository
{
    IQueryable Query();
}

var mock = Mock.Of]
    .Setup(x => x.Query(), users.AsQueryable())
    .Build();

var results = mock.Object.Query().Where(u => u.IsActive).ToList();

Performance Benchmarks

Run on .NET 8 (BenchmarkDotNet).

Mock Creation & Setup

LibraryTime (ns)Memory AllocatedGain vs Moq
Moq48,81210.37 KBBaseline
NSubstitute9,93712.36 KB~5× faster
NimbleMock1,4153.45 KB34× faster

Method Execution Overhead

LibraryTime (µs)Gain vs Moq
Moq~1.4Baseline
NSubstitute~1.6Slower
NimbleMock~0.62.3× faster

Verification

LibraryTime (ns)Memory AllocatedGain vs Moq
Moq1,7952.12 KBBaseline
NSubstitute2,1632.82 KBSlower
NimbleMock5850.53 KB3× faster

Powered by source generators — no runtime reflection!

Run the benchmarks yourself:

dotnet run --project tests/NimbleMock.Benchmarks --configuration Release

Migrating from Moq/NSubstitute

From Moq

// Moq
var mock = new Mock<IUserRepository>();
mock.Setup(x => x.GetById(1)).Returns(user);
// NimbleMock
var mock = Mock.Of()
    .Setup(x => x.GetById(1), user)
    .Build();

Verification is also more readable with the fluent API. See the full migration guide in the repository.

Lie‑Proofing: Avoid “Tests That Lie”

Unique feature: validate mocks against real endpoints.

var result = await LieProofing.AssertMatchesReal("https://api.staging.example.com");

if (!result.IsValid)
{
    // Log mismatches
}

Catches drifting APIs before production outages.

Final Thoughts

NimbleMock is built for .NET 8/9+ era: fast, safe, and joyful TDD. If you’re tired of slow suites or static‑mocking hacks, give it a try!

  • GitHub:
  • NuGet:

Feedback welcome — what pains do you have with current mocking libs? Would you switch for native statics and this speed?

⭐️ Star the repo if you like it, and let’s make testing fun again! 🚀

Back to Blog

Related posts

Read more »