简体   繁体   English

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

[英]How do you mock a void method that sets a read-only property?

I'm not very familiar with RhinoMocks and I'm trying to break into TDD on a side project of mine. 我对RhinoMocks不太熟悉,我想在我的一个副项目中闯入TDD。 I've been moving along okay until I hit a wall trying to get this behavior under test. 我一直在努力,直到撞到墙以试图测试这种行为。

    private int _result;
    public int Result { get { return _result; } }

    public void GetRandomValue()
    {
        Random n = new Random();
        _result = n.Next(1,100);
    }

Since this is an abstract class, how can I use RhinoMocks to verify that when I call the GetRandomValue method that the Result property is set? 由于这是一个抽象类,当我调用GetRandomValueValue方法设置了Result属性时,如何使用RhinoMocks进行验证? Or is this a necessary test? 还是这是必要的测试? Or a better way to design this small bit of code? 还是设计这少量代码的更好方法?

The way I would go about testing it is 我测试的方式是

var randomizerClass = new RandomizerClass();
ranomizerClass.GetRandomValue();
var result = ranomizerClass.Result;

Assert.IsTrue(result > 0 && result < 101);

And the ranomizerClass is the concrete implementation of the abstract class. ranomizerClass是抽象类的具体实现。 You don't need to separately test your abstract class since that will be done through the concrete implementation 您不需要单独测试抽象类,因为这将通过具体的实现来完成

也许您应该从抽象类中提取接口,并简单地使用相应的方法为其实现模拟?

Presumably when you instantiate the type, the _result field is set to it's default value of 0. So can't you just create an instance of the type, call the method, and then check the value of the Result property doesn't equal 0? 大概在实例化类型时, _result字段设置为默认值0。因此,您不能只创建该类型的实例,调用该方法,然后检查Result属性的值是否等于0 ?

It seems odd that a method called GetRandomValue , doesn't actually return anything. 名为GetRandomValue的方法实际上没有返回任何东西,这似乎很奇怪。 Is there a reason why this method doesn't return the result? 为什么没有这种方法返回结果的原因? Also, I would instantiate your Random type outside the scope of the method. 另外,我将在方法范围之外实例化您的Random类型。

How can you test that you're getting a random number? 如何测试您得到的是随机数? It's random, so you can't write a test that's actually asserting anything useful. 它是随机的,因此您不能编写实际上断言任何有用的测试。 You could make an IRandomNumberProvider interface and implement it on a RandomNumberProvider , then mock that for testing purposes, but you wouldn't be testing anything of value in my opinion. 可以做一个IRandomNumberProvider接口,并实现它在RandomNumberProvider ,然后嘲笑,对于测试的目的,但你不会在我看来是测试任何有价值的东西。 Even if you did like some other folks suggested and asserted that the number is between 1 and 100, you haven't tested anything useful in your code, you've just ensured that Microsoft's implementation of Next is working, which is a given. 即使您确实像其他人建议的那样并且断言数字在1到100之间,也没有测试代码中有用的任何内容,但是您只是确保了Microsoft的Next的实现可以正常工作。

Your GetRandomValue() method shouldn't set Result , though. 不过,您的GetRandomValue()方法不应设置Result It should return the result. 它应该返回结果。 Otherwise, you've introduced a side effect into your class, and that generally can cause weird, hard-to-track-down bugs. 否则,您会在类中引入副作用,并且通常会引起怪异且难以跟踪的错误。

In the cases where you need to test functionality in an abstract class, simply create a class that implements it in your test project. 在需要在抽象类中测试功能的情况下,只需创建一个在测试项目中实现该功能的类即可。

Eg given the following class 例如,鉴于以下课程

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);     
    }
}

Create a test class in your test project 在测试项目中创建测试类

public class StubMyClass : MyClass
{ 
} 

and then test it as follows 然后如下测试

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM