You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用NSubstitute ForPartsOf模拟异步方法时触发NullReferenceException

为什么使用NSubstitute的When处理异步带参数方法时会触发NullReferenceException?

这个问题我之前踩过坑,核心原因是NSubstitute的参数匹配器(比如Arg.Any<MyModel>())在异步lambda的上下文里无法正确初始化。

具体来说,当你在When里写async a => await a.MethodOne(Arg.Any<MyModel>())时,这个异步lambda会被编译成一个状态机。Arg.Any<T>的内部实现依赖于NSubstitute当前的调用拦截上下文,但await操作会让代码跳出这个上下文;等到后续执行匹配器逻辑时,NSubstitute的内部状态已经不在正确的调用上下文中了,导致匹配器访问了空引用,最终抛出NullReferenceException。

而同步方法或者无复杂参数的场景能正常运行,是因为同步lambda的逻辑全程在NSubstitute的调用拦截上下文里执行,参数匹配器可以正常获取所需的内部状态,不会出现空引用的情况。

解决方法其实很简单:

When方法的lambda只是用来匹配你要拦截的方法调用模式,不需要实际执行方法的异步逻辑(毕竟你已经用DoNotCallBase()阻止了基类实现),所以直接去掉lambda里的async和await就行:

[Fact]
public async Task Test6() {
    // Arrange
    MyClass myClass = Substitute.ForPartsOf<MyClass>();
    // 去掉async/await,直接匹配方法调用
    myClass.When(a => a.MethodOne(Arg.Any<MyModel>())).DoNotCallBase();
    // Act
    await myClass.MethodTwo();
    // Assert
    // 可以添加断言验证调用情况
    await myClass.Received().MethodOne(Arg.Any<MyModel>());
}

这样修改后,参数匹配器会在正确的调用上下文里执行,就不会再抛出NullReferenceException了。

内容的提问来源于stack exchange,提问作者Paul Michaels

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:49:48