您是否使用TestInitialize或测试类构造函数来准备每个测试?为什么?

Ant*_*ean 65 .net constructor unit-testing

这个问题涉及使用MSTest在Visual Studio中进行单元测试(这很重要,因为MSTest的执行顺序).标记为[TestInitialize]的方法和测试类构造函数都将在每个测试方法之前运行.

所以,问题是,你在这些领域中倾向于做什么?你是否避免在两者中进行某些活动?你的理由是什么:风格,技术,迷信?

Ant*_*ean 52

构造函数只是该语言提供的结构.每个测试框架似乎都有自己的受控生命周期"初始化".您可能只会使用构造函数来改变您的本地人.

MSTest:您可以获得每个测试类的全新实例TestMethod.这可能是唯一可以在构造函数,初始化程序或测试方法中改变局部变量并且不影响其他测试方法的情况.

public class TestsForWhatever
{
    public TestsForWhatever()
    {
        // You get one of these per test method, yay!
    }

    [TestInitialize] 
    public void Initialize() 
    {
        // and one of these too! 
    }

    [TestMethod]
    public void AssertItDoesSomething() { }

    [TestMethod]
    public void AssertItDoesSomethingElse() { }
}
Run Code Online (Sandbox Code Playgroud)

MSpec:你只有一次Establish,并Because为所有的断言(It).所以,不要在断言中改变你的本地人.并且不依赖于基本上下文中的本地变异(如果使用它们).

[Subject(typeof(Whatever))]
public class When_doing_whatever
{
    Establish context = () => 
    { 
        // one of these for all your Its
    };

    Because of = () => _subject.DoWhatever();

    It should_do_something;
    It should_do_something_else;
}
Run Code Online (Sandbox Code Playgroud)

  • 您可能还会指出`[ClassInitialize]`每次测试运行只运行一次(在所有内容之前),因此它可以用于任何昂贵的设置例程. (5认同)
  • -1:你不应该讨厌你的问题; 实际上,这很有道理.例如,参见[xUnit.net](https://github.com/xunit/xunit):它建议使用构造函数作为*测试用例初始化程序."只是一种由语言提供的结构"并不是一件小事; 任何人编写任何类型的框架(包括测试框架)都应该*尝试重新发明轮子,并使用明确定义的标准(比如,你知道,使用构造函数来初始化东西,等等). (5认同)
  • 令人惊讶的是,Microsoft 可以编写整个网页而不提供您在这个简单直接的答案中提供的基本信息。做得好。 (2认同)

T. *_*ter 18

以下是我在TestInitialize中发现的一些优点.

  • 在实例化测试类之前,无法访问某些环境变量(例如TestContext).
  • 可以通过标记基本TestInitialize方法abstract来要求使用派生类进行实现.
  • 可以轻松覆盖基本TestInitialize方法,并确定是在派生impl之前,之后还是根本调用基本impl.相反,如果从基本测试类派生测试类,则在无参数构造函数的情况下,无论您是否打算使用基本ctor,都将调用它.
  • 它的明确定义使意图清晰,并补充了TestCleanup方法.你可能会争辩说你可以为每个构造函数创建一个析构函数,但不能保证MS Test会像你期望的那样处理析构函数.

  • 我发现 MSTest *确实* 在每次测试运行后运行一个 `public void Dispose` 方法。它必须是公共的,并且您实现`IDisposable` 无关紧要:您不能显式实现该接口。 (2认同)

小智 15

使用TestInitialize()或ClassInitialize()而不是测试类实例或静态构造函数的主要优点是它的显式特性.它清楚地表明您在测试之前正在进行一些设置.持续这样做应该从长远来看提高可维护性.

  • 我不同意.什么比构造函数更清晰?当然,您必须知道每个测试都会获得一个新的测试类实例,但这是您真正应该知道的.并且它不像`TestInitialize`这样一个明显的名称,不会引起任何混淆:/sf/ask/1609987151/. (8认同)

Oha*_*der 6

我说除非你需要,否则使用构造函数TestContext

  1. 如果你能让事情变得简单,为什么不呢?构造函数比魔法属性更简单。
  2. 您可以使用readonly这是测试初始化​​中的一件大事,您想要为测试准备不应该更改的内容(理想情况下您准备的内容也是不可变的)。

  • +1 为只读。当我看到你的答案时,我刚刚删除了我的问题。但我通常会以另一种方式思考:我使用 TestInitialize 除非我想要一个只读属性,因为它看起来更适合测试上下文的“语言”。但这只是一个设计决定。我对这两种方法都满意。 (2认同)