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

如何在NSubstitute中模拟内部成员并通过单元测试?

解决NSubstitute模拟内部辅助类的问题

你的问题主要出在两个地方:一是直接替代A类后试图访问其只读内部字段_bHelper,二是错误地在非替代对象的方法调用中使用了Arg.Any匹配器。下面给你两种可行的解决方案:

方案一:通过构造函数注入依赖(推荐)

这种方式更符合依赖注入原则,也让测试逻辑更清晰。首先修改A类,添加一个接受B实例的构造函数,这样测试时可以传入模拟的B对象:

[assembly: InternalsVisibleTo("Tests")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
namespace NS.B {
    public class A {
        internal readonly B _bHelper;
        
        // 供测试使用的构造函数,传入B的实例
        public A(B bHelper) {
            _bHelper = bHelper;
        }
        
        // 保留默认构造函数,用于正常业务逻辑
        public A() : this(new B()) {}

        public int GetBag(string s1, string s2){
            return _bHelper.GetBag(s1, s2);
        }
    }
}

然后修改测试代码,先模拟B类,再传入A的实例:

[Fact]
public void checkBaggageRule() {
    // 模拟内部类B
    var mockB = Substitute.For<B>();
    // 设置当调用GetBag时,无论传入什么参数都返回30
    mockB.GetBag(Arg.Any<string>(), Arg.Any<string>()).Returns(30);
    
    // 创建A的实例,传入模拟的B
    var aInstance = new A(mockB);
    var result = aInstance.GetBag("oo", "L");
    
    Assert.Equal(30, result);
}

这样做的好处是不需要依赖反射,代码更健壮,也符合良好的设计原则。

方案二:使用反射修改只读字段(备选,适用于无法修改原类的情况)

如果因为遗留代码等原因无法修改A类的构造函数,可以通过反射来替换_bHelper字段的值:

[Fact]
public void checkBaggageRule() {
    var mockB = Substitute.For<B>();
    mockB.GetBag(Arg.Any<string>(), Arg.Any<string>()).Returns(30);
    
    // 创建A的默认实例
    var aInstance = new A();
    // 通过反射获取_bHelper字段
    var bHelperField = typeof(A).GetField("_bHelper", BindingFlags.Instance | BindingFlags.NonPublic);
    // 替换字段值为模拟的B对象
    bHelperField.SetValue(aInstance, mockB);
    
    var result = aInstance.GetBag("oo", "L");
    Assert.Equal(30, result);
}

为什么原来的代码会报错?

你之前直接Substitute.For<A>()得到的是A的替代实例,但_bHelper是只读内部字段,NSubstitute不会自动替换这个字段的值,此时_bHelper要么是null,要么是B的实际实例。当你调用repo._bHelper.GetBag(Arg.Any<string>(), Arg.Any<string>())时,Arg.Any被用在了非替代对象的方法调用中,这违反了NSubstitute的规则——参数匹配器只能用于替代对象的方法调用参数,所以才会抛出UnexpectedArgumentMatcherException。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:44:15