如何模拟设置只读属性的void方法

本文关键字:只读属性 void 方法 设置 何模拟 模拟 | 更新日期: 2023-09-27 18:22:02

我对RhinoMocks不是很熟悉,我正试图在我的一个附带项目上突破TDD。我一直进展顺利,直到我碰壁试图测试这种行为。

    private int _result;
    public int Result { get { return _result; } }
    public void GetRandomValue()
    {
        Random n = new Random();
        _result = n.Next(1,100);
    }

由于这是一个抽象类,我如何使用RhinoMocks来验证当我调用GetRandomValue方法时是否设置了Result属性?还是这是一个必要的测试?还是设计这一小段代码的更好方法?

如何模拟设置只读属性的void方法

我测试它的方法是

var randomizerClass = new RandomizerClass();
ranomizerClass.GetRandomValue();
var result = ranomizerClass.Result;
Assert.IsTrue(result > 0 && result < 101);

ranomizerClass是抽象类的具体实现。您不需要单独测试抽象类,因为这将通过具体的实现

来完成

也许您应该从抽象类中提取接口,并用相应的方法简单地实现它的mock?

假设在实例化类型时,_result字段设置为其默认值0。那么,你就不能创建一个类型的实例,调用该方法,然后检查Result属性的值是否不等于0吗?

一个名为GetRandomValue的方法实际上没有返回任何内容,这似乎很奇怪。这个方法不返回结果是有原因的吗?此外,我会在方法的范围之外实例化您的Random类型。

如何测试您得到的是一个随机数?它是随机的,所以你不能写一个测试来断言任何有用的东西。您可以制作一个IRandomNumberProvider接口并在RandomNumberProvider上实现它,然后出于测试目的对其进行模拟,但在我看来,您不会测试任何有价值的东西。即使你像其他人建议并断言的那样,这个数字在1到100之间,你也没有在代码中测试任何有用的东西,你只是确保了微软对Next的实现是有效的,这是既定的。

不过,您的GetRandomValue()方法不应该设置Result。它应该返回结果。否则,您在类中引入了一个副作用,这通常会导致奇怪的、难以追踪的错误。

在需要在抽象类中测试功能的情况下,只需创建一个在测试项目中实现它的类即可。

例如,给定以下类别的

public abstract class MyClass
{
    private int _result;     
    public int Result { get { return _result; } }      
    public void GetRandomValue()     
    {         
        Random n = new Random();         
        _result = n.Next(1,100);     
    }
}

在测试项目中创建一个测试类

public class StubMyClass : MyClass
{ 
} 

然后按照测试

[Test]
public void ShouldSetResultAfterCallingGetRandomValue()
{ 
    var myClass = new StubMyClass();
    myClass.GetRandomValue();
    int expected = 1234;
    Assert.That(myClass.Result, Is.EqualTo(expected));
}