78

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

public class MyTest
{
    private MyClass myClass;

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

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

关于与默认构造函数有什么好的/坏的做法,TestFixtureSetup或者没有任何区别?

4

9 回答 9

65

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

我使用[SetUp][TearDown]标记了每次测试之前和之后要执行的代码的方法,并且类似地[TestFixtureSetUp]标记[TestFixtureTearDown]了在夹具中的所有测试运行之前和之后只执行一次代码的方法。

我想您可能可以将 替换[TestFixtureSetUp]为构造函数(尽管我没有尝试过),但这似乎只是违反了标记方法提供的明确约定。

于 2008-10-17T16:02:41.250 回答
19

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

对于 nunit,我在这种情况下的最佳实践是使用文档中描述的TestFixtureSetUpTestFixtureTearDownSetUp和方法。TearDown

I think it also helps me when I don't think of an nUnit test fixture as a normal class, even though you are defining it with that construct. I think of them as fixtures, and that gets me over the mental hurdle and allows me to overlook this issue.

于 2008-10-17T18:00:17.910 回答
13

One thing you can't do with [TestFixtureSetup] that you can do in the constructor is receive parameters from the [TestFixture] .

If you want to parameterise your test fixture, then you will have to use the constructor for at least some of the set-up. So far, I've only used this for integration tests, e.g. for testing a data access layer with multiple data providers:

[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)
    {
        ...
    }
}
于 2010-08-27T01:36:39.850 回答
10

There is difference between constructor and method marked with [TestFixtureSetUp] attribute. According to NUnit documentation:

It is advisable that the constructor not have any side effects, since NUnit may construct the object multiple times in the course of a session.

So if you have any expensive initialization it is better to use TestFixtureSetUp.

于 2012-01-11T10:37:20.863 回答
9

I have often wondered what the need for [TestFixtureSetUp] was, given that there is a simple, well understood first class language construct that does exactly the same thing.

My preference is to use constructors, to take advantage of the readonly keyword ensuring member variables cannot be reinitialised.

于 2009-05-06T16:26:22.633 回答
4

[TestFixtureSetUp] and [TestFixtureTearDown] are for whole test class. runs only once.

[SetUp] and [TearDown] are for every test method(test). runs for every test.

于 2016-02-09T10:51:07.173 回答
3

An important difference between constructor and TestFixtureSetUp is that, in NUnit 2 at least, constructor code is actually executed on test enumeration, not just test running, so basically you want to limit ctor code to only populating readonly, i.e. parameter, values. Anything that causes side-effects or does any actual work needs to either be wrapped in a Lazy or done in the TestFixtureSetUp / OneTimeSetUp. So, you can think of the constructor as solely a place to configure the test. Whereas the TestFixtureSetUp is where the test fixture, the required initial state of the system before tests are run, is initialized.

于 2016-03-16T17:40:09.657 回答
2

I think I have a negative good answer - the reason to use a constructor instead of the attribute is when you have an inheritence between test classes.

Only one method annotated with [TestFixtureSetup] will be called (on the concrete class only), but the other fixture initializers will not. In this case I'd rather put the initialization in the constructor, which has a well-defined semantics for inheritance :)

于 2009-07-25T07:13:49.160 回答
-2

The constructor and the SetUp methods are used differently:
The constructor is run only once.
However, the SetUp methods are run multiple times, before every test case is executed.

于 2012-06-13T09:13:36.293 回答