单元测试运行两次

时间:2017-06-02 06:55:19

标签: c# nunit

我有一些测试代码正在初始化一些成员,这些成员应该在开始时只做一次。这就是我使用构造函数的原因:

[TestFixture]
public class MyTestClass
{
    private readonly IUnitTestGeometryProvider m_GeometryProvider;


    public MyTestClass()
    {
        // do some heavy init-op
    }

    private IEnumerable<TestCaseData> TestCases()
    {
        yield return new TestCaseData(this.m_GeometryProvider.GetPolyline())
            .Throws(typeof(ArgumentException));
    }

    [TestCaseSource("TestCases")]
    public double Check_GetReducedArea_For_Invalid_Arguments(IGeometry theGeom)
    {
        return theGeom.GetReducedArea();
    }
}

我知道使用FixtureSetup - 属性初始化测试的约定,例如来自this question on SO。但是我注意到方法TestCases在使用该属性标记的方法之前执行,因此在评估不同的测试用例时我遇到了NullReferenceException,因为m_GeometryProvidernull时间。

所以我调试了我的代码并在构造函数中设置了一个断点。我注意到,它甚至在任何测试运行之前执行了两次。我假设每个测试用例都有自己的MyTestClass实例,但由于我有三个不同的测试用例,并且运行两次的构造函数不能解释它。

由于初始化很重,我想只执行一次。有没有办法保证这个?我想避免使用static成员,因为它经常吸引同事大量使用其他static成员,因为已经存在。此外,我认为test-init特定于我的MyTestClass的一个实例而不是类本身 - 假设只有一个。

我正在使用NUnit 2.5.10。

1 个答案:

答案 0 :(得分:4)

基本上,NUnit保留随时根据需要构建fixture对象的权利。因此,您应该避免在构造函数中进行大量初始化,尤其是在运行测试时仅需要进行一些初始化时。

通常,执行测试的初始化应该在TestFixtureSetUp方法中完成,该方法只在每次执行夹具时运行一次。但是,当您使用TestCaseSource属性生成测试用例时,这会更复杂。

因为必须首先执行TestCase以便在它们运行之前创建测试,所以必须创建对象的实例来执行此操作。然后,当运行测试时,会创建另一个实例以运行它们。在你的问题中没有足够的信息来弄清楚为什么对你的构造函数有两个“额外”的调用,但这要么是由于代码的某些其他方面,要么是你正在使用的旧版NUnit中的一个错误。您必须单步执行这些构造函数调用并检查堆栈跟踪以查看调用它们的内容。

你的m_GeometryProvider成员是否在TestCases方法之外的任何地方使用?如果没有,您可以通过使其成为在该方法中创建的临时字段来简化操作。然后,您可以通过使TestCases方法静态来消除额外的构造函数调用。你说你不喜欢这样,但这是我们推荐的。事实上,在NUnit 3.0及更高版本中,它必须是静态的。

如果除了创建几何提供程序之外还有其他初始化需要运行测试,那么应该使用TestFixtureSetUp方法。