何时使用TestFixtureSetUp属性代替默认构造函数?


75

NUnit文档没有告诉我何时使用带有a的方法TestFixtureSetup以及何时在构造函数中进行设置。

public class MyTest
{
    private MyClass myClass;

    public MyTest()
    {
        myClass = new MyClass();
    }

    [TestFixtureSetUp]
    public void Init()
    {
        myClass = new MyClass();
    }
}

关于TestFixtureSetup默认构造函数是否有好的/不好的做法,或者没有任何区别吗?


由于这是总是被问了一个问题经常考虑这个这个(对于相同的讨论MSTest)。但是要当心夹具设置对测试可读性的副作用(请在此处此处)。
Massood Khaari 2015年

只给我一分钱:当有许多测试的基类时,这很有用。派生类将自动运行父类中定义的TestFixtureSetup。除非您明确地调用构造函数,否则您将无法做到这一点(取决于您拥有多少个派生类,这可能是一个问题,也可能不是一个问题)
Nelson Rodriguez,

Answers:


17

我认为这是nUnit团队尚未解决的问题之一。但是,有一个出色的xUnit项目看到了这个确切的问题,并认为构造函数是在测试夹具初始化中使用的好东西。

对于NUnit的,在这种情况下,我最好的做法是使用TestFixtureSetUpTestFixtureTearDownSetUp,和TearDown如文档中描述的方法。

当我不将nUnit测试治具视为普通类时,即使您使用该构造定义它,我认为它也对我有帮助。我将它们视为固定装置,这使我摆脱了心理障碍,并让我忽略了这个问题。


2
请注意,xUnit文章建议Setups(以及构造函数)通常是一个不好的主意,这会使测试代码难以遵循,而不是构造函数优于Setups。但是,无参数构造函数是真正需要它的人的最后选择。另请参阅:测试样式并避免设置/拆卸
Massood Khaari 2015年

64

为什么需要在测试类中使用构造函数?

我使用[SetUp][TearDown]代码标记方法前和每次测试后执行,同样[TestFixtureSetUp][TestFixtureTearDown]标示为代码的方法来进行前,在灯具的所有测试已运行后只执行一次。

我猜您可能可以[TestFixtureSetUp]用构造函数代替(尽管我还没有尝试过),但这似乎与标记方法提供的明确约定有所不同。


4
我不知道为什么需要构造函数,但是我也不知道为什么需要TestFixtureSetUp。我知道setup,teardown和testfixtureteardown属性。我只是不知道构造函数和testfixturesetup属性之间的区别。
Paco

4
只是为了回答您的问题。如果您具有参数化的测试夹具,则需要在测试类中使用构造函数。
oderibas

13

有一件事你不能做[TestFixtureSetup],你可以在构造函数中做的是收到的参数[TestFixture]

如果要参数化测试夹具,则必须至少使用构造函数进行某些设置。到目前为止,我仅将其用于集成测试,例如,用于测试具有多个数据提供程序的数据访问层:

[TestFixture("System.Data.SqlClient",
  "Server=(local)\\SQLEXPRESS;Initial Catalog=MyTestDatabase;Integrated Security=True;Pooling=False"))]
[TestFixture("System.Data.SQLite", "Data Source=MyTestDatabase.s3db")])]
internal class MyDataAccessLayerIntegrationTests
{
    MyDataAccessLayerIntegrationTests(
        string dataProvider,
        string connectionString)
    {
        ...
    }
}

10

[TestFixtureSetUp]属性标记的构造函数和方法之间存在区别。根据NUnit文档:

建议构造函数不要有任何副作用,因为NUnit可能在会话过程中多次构造对象。

因此,如果您进行任何昂贵的初始化,最好使用TestFixtureSetUp


1
这是假定标记为TestFixtureSetUp的方法是静态的。否则,除非将测试实例扔掉而不被NUnit使用,否则构造函数将不可能被更频繁地调用,我对此表示怀疑。
jpierson

9

[TestFixtureSetUp]鉴于有一个简单的,易于理解的一流语言构造可以执行完全相同的操作,因此我经常想知道需要什么。

我的首选是使用构造函数,以利用readonly关键字来确保成员变量无法重新初始化。


4
readonly关键字不能确保成员不会被修改。如果成员是一个类,则可以在测试中修改该类的内部状态,并将此状态转移到下一个测试方法中(因为nunit不会在每次测试运行之间重新创建类)
Pete

4

[TestFixtureSetUp]并且[TestFixtureTearDown]适用于整个测试课程。只运行一次。

[SetUp]并且[TearDown]适用于每种测试方法(测试)。为每个测试运行。


3

构造函数和TestFixtureSetUp之间的重要区别在于,至少在NUnit 2中,构造函数代码实际上是在测试枚举上执行的,而不仅仅是在测试运行时执行的,因此,基本上,您希望将ctor代码限制为仅填充只读(即参数)值。任何会引起副作用或进行任何实际工作的东西都需要包装在Lazy中或在TestFixtureSetUp / OneTimeSetUp中完成。因此,您可以将构造函数视为配置测试的唯一场所。而TestFixtureSetUp是测试夹具的初始化位置,是测试运行之前系统所需的初始状态。


这是一个好点,不确定当前的相关性,但是需要考虑的事情。
aiodintsov '19

2

我认为我的回答是负面的-使用构造函数而不是属性的原因是当您在测试类之间继承时。

[TestFixtureSetup]将仅调用带有注解的一个方法(仅在具体类上),而不会调用其他夹具初始化器。在这种情况下,我宁愿将初始化放在构造函数中,该构造函数具有明确定义的继承语义:)


2
从NUnit 2.5开始,这种情况已经改变。现在将调用所有用[TestFixtureSetup]注释的方法。
oderibas

-2

构造函数和SetUp方法的用法不同:
构造函数仅运行一次。
但是,SetUp在每个测试用例执行之前,这些方法会运行多次。


1
您是指[SetUp],而OP是指[TestFixtureSetUp]
某天,2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.