替换部分模拟对象中的只读属性

本文关键字:只读属性 对象 模拟 替换部 | 更新日期: 2023-09-27 17:57:37

我正在测试一个MVC控制器,它依赖于基类上只读属性返回的值。

这个属性的getter在被调用时抛出一个异常,因为它依赖于HttpContext(和其他讨厌的东西),我宁愿避免嘲笑它。

这就是我迄今为止所尝试的:

controller = Substitute.ForPartsOf<MyController>(
    Substitute.For<SomeDependency>(),
);
controller.UserInfo.Returns(new UserInfo());

然而,一旦访问UserInfo,就会引发异常。

基类的属性为:

public UserInfo UserInfo
{
    get
    {
        // HttpContext dependent stuff
    }
}

我曾尝试将基类属性设置为virtual,但后来出现了Castle代理异常。

替换部分模拟对象中的只读属性

我想您可能遇到了另一个问题。NSubstitute能够处理虚拟属性的替换。下面是一个演示的小程序

public class SubstitutedClass
{
    public virtual int SubstitutedProperty { get { throw new InvalidOperationException(); }  }
}
internal class Program
{
    private static void Main(string[] args)
    {
        var test2 = Substitute.For<SubstitutedClass>();
        test2.SubstitutedProperty.Returns(10);
        Console.WriteLine(test2.SubstitutedProperty);
    }
}

EDIT:关于ForPartsOf的使用,我认为不可能以这种方式覆盖属性,因为无法通知NSubstitute我们不希望它调用基代码。这就是为什么文件中提到不建议使用部分子

您可以更改基类以返回虚拟函数的值;则该虚拟函数将被替换。呼叫者没有签名更改。虽然这是一个黑客,你会得到你需要的

public class SubstitutedClass
{
    public virtual int SubstitutedProperty { get { return InnerValue(); } }
    public virtual int InnerValue() { throw new InvalidOperationException(); }
}
var test2 = Substitute.ForPartsOf<SubstitutedClass>();
test2.When(t => t.InnerValue()).DoNotCallBase();
test2.InnerValue().Returns(10);