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

使用NSubstitute时传递Arg.Any<int>()作为参数引发NullReferenceException问题排查

为什么用Arg.Any()调用Customer.CalculateWage会抛出NullReferenceException?

你碰到的这个坑其实是NSubstitute里很常见的新手误区——Arg.Any()只是用来定义替代对象的参数匹配规则的,不能直接当作实际方法调用的参数传入。

拆解问题原因:

  1. 用具体ID时正常运行的逻辑:
    当你传入anyId(比如1)调用CalculateWage时,你的替代gateway已经被设置为:只要调用GetWorkingStatistics时传入任意int参数(因为你用了Arg.Any<int>()来匹配),就返回预设的workingStatistics对象。所以_gateway.GetWorkingStatistics(id)能拿到有效的实例,后续访问ws.PayHourly等属性自然不会报错。

  2. 用Arg.Any()调用时报错的逻辑:
    Arg.Any<int>()本质上是NSubstitute内部的特殊标记,它的作用是告诉NSubstitute:“当这个替代对象的方法被调用时,不管传入什么int参数,都匹配这个规则”——但这个标记只能在设置替代规则的时候用(比如gateway.GetWorkingStatistics(Arg.Any<int>()).Returns(...)这一步)。
    当你把它直接传给CalculateWage(Arg.Any<int>())时,这是在实际调用被测方法,此时NSubstitute不会把它当作匹配规则,而是会把它转换成一个不触发预设规则的占位值,导致_gateway.GetWorkingStatistics(id)返回null,后续访问ws.PayHourly就会抛出NullReferenceException。

修正后的测试代码

只需要把调用CalculateWage时的Arg.Any<int>()换成任意有效的int值就行——哪怕是和你设置规则时用的不一样的int也没关系,因为你已经用Arg.Any<int>()让gateway匹配所有int参数了:

[TestFixture]
public class CustomerTestsWithNSubstitute {
    [Test]
    public void CalculateWage_HourlyPayed_ReturnsCorrectWage() {
        var gateway = Substitute.For<IDbGateway>();
        var workingStatistics = new Business.Demo.WorkingStatistics() {
            PayHourly = true,
            HourSalary = 100,
            WorkingHours = 10
        };
        // 设置匹配任意int参数的返回规则
        gateway.GetWorkingStatistics(Arg.Any<int>()).Returns(workingStatistics);
        const decimal expectedWage = 100 * 10;
        var sut = new Customer(gateway);
        // 这里用任意有效的int值即可,比如1、0、100都可以
        decimal actual = sut.CalculateWage(1);
        Assert.That(actual, Is.EqualTo(expectedWage).Within(0.1));
    }
}

关键要点总结

  • Arg.Any<T>()、Arg.Is<T>()这类方法仅用于配置替代对象的调用匹配规则,不能作为实际方法调用的参数。
  • 实际调用被测方法时,传入符合匹配规则的真实参数值即可——哪怕是随便选的有效值,只要能触发你之前设置的替代规则就行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 21:32:47