N-Unit中的TestCaseSource

时间:2012-10-10 14:30:08

标签: c# .net unit-testing nunit testcasesource

我正在写一些N-Unit测试,我遇到了一些困难。我正在尝试将测试连接到我的代码中的TestCaseSource,但它似乎没有正确构建对象。

这是我的测试方法:

    [Test, TestCaseSource(typeof(TestCaseStuff), "GetTestCases", Category = "Release")]
    public void WithdrawMoney(TestCaseStuff tc)
    {
        double newBalance = AccountBalance - tc.amt;
        if (newBalance < 0)
        {
            Assert.Fail(String.Format("You can't withdraw {0}! You've maxed" +
                "out your bank account.", tc.amt.ToString("C2")));
        }

        AccountBalance = newBalance;
        Assert.Pass(String.Format("Your new balance is {0}.", 
        (AccountBalance).ToString("C2")));
    }

我的TestCaseSource

public class TestCaseStuff
{
    public double amt { get; set; }

    public TestCaseStuff()
    {
        Random rnd = new Random();
        this.amt = rnd.Next(0, 20);
    }

    [Category("Release")]
    public IEnumerable<TestCaseData> GetTestCases()
    {
        for (int i = 0; i < 500; i++)
        {
            yield return new TestCaseData(this);
        }
    }
}

这主要是作为概念的证明,因此当用复杂对象编写实际测试时,我会知道我可以像上面那样编写一个循环并在我的对象中放置随机值。但是,返回到我的测试方法的每个TestCaseStuff实例都是相同的。

更新

以下答案是正确的。当我将它传递给N-Units TestCaseData对象时,我假设(错误地)它只是按值传递该实例。显然,它是通过引用完成的,这就是为什么值总是相同的。

最重要的是,我错误地使用了Random类。这不是我经常处理的事情,但我没有正确地阅读它。如下面的链接所述,当使用Random和它的默认构造函数时,种子值是从系统时钟派生的。因此,如果您快速连续实例化多个Random个对象,它们将共享相同的默认种子值并生成相同的值。

因此,由于这些发展,我的代码现在为:

public class TestCaseStuff
{
    public double amt { get; set; }
    private static readonly Random rnd = new Random();

    public TestCaseStuff()
    {
        this.amt = rnd.Next(0, 20);
    }

    [Category("Release")]
    public IEnumerable<TestCaseData> GetTestCases()
    {
        for (int i = 0; i < 500; i++)
        {
            yield return new TestCaseData(new TestCaseStuff());
        }
    }

}

2 个答案:

答案 0 :(得分:3)

上面的代码只会实例化TestCaseSource的一个副本并继续提供相同的值。

如果打算在每个循环中生成一个随机数,我认为你应该创建一个Random对象的静态实例,并在每次创建一个新的TestCaseStuff对象时从中生成一个数字

我会像这样重写TestCaseStuff:

public class TestCaseStuff
{
    // Static instance of a random number generator.
    private static readonly Random RNG = new Random();

    public double amt { get; set; }

    public TestCaseStuff()
    {
        this.amt = RNG.Next(0, 20);
    }

    [Category("Release")]
    public IEnumerable<TestCaseData> GetTestCases()
    {
        for (int i = 0; i < 500; i++)
        {
            // NOTE: You need to create a new instance here.
            yield return new TestCaseData(new TestCaseStuff());
        }
    }
}

答案 1 :(得分:2)

每次调用时都在创建一个新的Random实例:

yield return new TestCaseData(this);

尝试将其移出循环,您应该开始获取随机值。

发现这篇文章解释得很好! How do I seed a random class to avoid getting duplicate random values