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

使用NSubstitute模拟带私有Setter的属性遇异常,求解决方案

解决NSubstitute无法设置属性返回值的问题

你遇到的这个错误,核心原因是NSubstitute无法拦截非虚拟的类成员,而你的MyProperty1是普通的非虚拟自动属性,NSubstitute没法替换它的get访问逻辑,所以Returns方法找不到可绑定的调用,就抛出了CouldNotSetReturnDueToNoLastCallException。

下面给你几种可行的解决方案:

方案1:修改原类,将属性改为虚拟(推荐,如果有权限修改原代码)

NSubstitute只能模拟接口、抽象类,或者类中的虚拟/抽象成员。把MyProperty1改成虚拟属性后,NSubstitute就能拦截它的get操作并配置返回值了:

public class MyClass { 
    // 添加virtual关键字
    public virtual int MyProperty1 { get; private set; } 
    public int MyProperty2 { get; private set; } 
    public MyClass(){}
    public MyClass(int myProperty2) => MyProperty2 = myProperty2; 
}

修改后你的测试代码就能正常运行,fake.MyProperty1.Returns(5)会正确覆盖属性的返回值。

方案2:用反射绕过私有set设置属性值(如果不能修改原类)

因为MyProperty1有private set,我们可以通过反射直接调用它的私有set方法,或者修改自动属性对应的后台字段来设置值:

方式A:调用私有set方法

[Fact]
public void MyTest() {
    var myObj = new MyClass(3);
    // 获取MyProperty1的属性信息
    var propInfo = typeof(MyClass).GetProperty(
        nameof(MyClass.MyProperty1), 
        System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance
    );
    // 获取私有set方法
    var setter = propInfo.GetSetMethod(nonPublic: true);
    // 调用set方法设置值为5
    setter.Invoke(myObj, new object[] { 5 });

    // 执行断言
    Assert.Equal(5, myObj.MyProperty1);
}

方式B:直接修改自动属性的后台字段

对于C#的自动属性,编译器会生成一个名为_<PropertyName>的私有后台字段(比如MyProperty1对应_MyProperty1),我们可以直接修改这个字段的值:

[Fact]
public void MyTest() {
    var myObj = new MyClass(3);
    // 获取后台字段
    var fieldInfo = typeof(MyClass).GetField(
        "_MyProperty1", 
        System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance
    );
    // 设置字段值
    fieldInfo.SetValue(myObj, 5);

    // 执行断言
    Assert.Equal(5, myObj.MyProperty1);
}

为什么你的原测试代码会失败?

你用NSubstitute.Substitute.For<MyClass>(3)创建的是MyClass的部分模拟对象,但对于非虚拟的MyProperty1,NSubstitute无法替换它的get逻辑,调用fake.MyProperty1时还是会执行原类的get操作(返回默认值0),而Returns方法需要先捕获到一个可模拟的调用才能配置返回值,所以就抛出了找不到调用的异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:54:06