NimbleMock:一个现代、极快的 .NET Mocking 库(比 Moq 快 34 倍)

发布: (2025年12月14日 GMT+8 07:57)
5 min read
原文: Dev.to

Source: Dev.to

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

为什么我创建了 NimbleMock

多年来,我在企业 .NET 应用中遇到了常见的 Mock 痛点:

  • 冗长的设置,需要为大型接口(为测试一个功能而 mock 20+ 方法)。
  • 性能损耗,来自运行时代理(Moq 中的 Castle.DynamicProxy)——在大型测试套件中创建和验证速度慢。
  • 静态/密封类的 Mock 地狱——没有原生支持,需要付费工具或包装器。
  • 异步和泛型问题——出现意外的 null Task 或笨拙的类型推断。
  • 脆弱的测试——本地通过的 Mock 在生产环境中因不匹配真实 API 而失败。

Moq 经受了考验,NSubstitute 代码简洁易读,但两者都没有充分利用现代 .NET 的源码生成器实现零开销。

NimbleMock 通过编译时魔法解决这些问题:无需运行时代理,激进的内联以及栈分配。结果?创建 Mock 快 34 倍验证快 3 倍,在典型场景下零分配。

关键特性

  • 部分 Mock – 只 Mock 需要的部分;未 Mock 的方法会抛出 NotImplementedException 以便及早发现。
  • 原生静态/密封类 Mock – 直接 Mock DateTime.NowEnvironment 等。
  • 一流的异步支持 – 对 TaskValueTask 无缝兼容。
  • 泛型类型推断 – 完全支持嵌套泛型(例如 EF Core 的 IQueryable)。
  • 流畅、可链式的 API – 受 NSubstitute 与 Moq 最佳实践启发。
  • 防“说谎”验证 – 可选的运行时校验,针对真实的预发布 API 捕获过时的 Mock 结构。
  • 编译时分析器 – 提前捕获错误(例如忘记对异步方法使用 SetupAsync 时给出警告)。

MIT 许可证,开源,欢迎贡献!

快速开始

通过 NuGet 安装

dotnet add package NimbleMock

基本示例

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();

部分 Mock(完美适用于上帝接口)

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

// 未 Mock 的方法会抛出,以保证安全

静态 Mock

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

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

泛型示例

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();

性能基准

在 .NET 8(BenchmarkDotNet)上运行。

Mock 创建与设置

时间 (ns)分配的内存相对于 Moq 的提升
Moq48,81210.37 KB基准
NSubstitute9,93712.36 KB~5× 更快
NimbleMock1,4153.45 KB34× 更快

方法执行开销

时间 (µs)相对于 Moq 的提升
Moq~1.4基准
NSubstitute~1.6更慢
NimbleMock~0.62.3× 更快

验证

时间 (ns)分配的内存相对于 Moq 的提升
Moq1,7952.12 KB基准
NSubstitute2,1632.82 KB更慢
NimbleMock5850.53 KB3× 更快

由源码生成器驱动——无运行时反射!

自行运行基准:

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

从 Moq/NSubstitute 迁移

从 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();

验证同样更具可读性,使用流式 API。完整迁移指南请查看仓库。

防“说谎”验证:避免“说谎的测试”

独特功能:将 Mock 与真实端点进行校验。

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

if (!result.IsValid)
{
    // 记录不匹配项
}

在生产故障前捕获 API 漂移。

最后感想

NimbleMock 为 .NET 8/9+ 时代而生:快速、安全、让 TDD 充满乐趣。如果你厌倦了缓慢的测试套件或静态 Mock 的 hack,快来试试吧!

  • GitHub:
  • NuGet:

欢迎反馈——你在当前 Mock 库中遇到哪些痛点?是否会因为原生静态支持和这般速度而切换?

⭐️ 给仓库点星,如果你喜欢它,让我们一起让测试重新变得有趣! 🚀

Back to Blog

相关文章

阅读更多 »