如何在派生类中使用NUnit进行设置?

7
如果我有以下代码:
[TestFixture]
public class MyBaseTest
{
    protected ISessionManager _sessionManager;

    [SetUp]
    public void SetUp() { /* some code that initializes _sessionManager */ }
}

[TestFixture]
public class MyDerivedTest : MyBaseTest
{
    IBlogRepository _repository;

    [SetUp]
    public void SetUp() { /* some code that initializes _repository */ }

    [Test]
    public void BlogRepository_TestGoesHere() { /* some tests */ }
}

...NUnit不会调用基本的SetUp程序,这是可以预料的,并且我本身对此没有任何问题。我可以让派生的SetUp首先调用基本的SetUp,就像这样:

[TestFixture]
public class MyDerivedTest : MyBaseTest
{
    IBlogRepository _repository;

    [SetUp]
    public new void SetUp()
    {
        base.SetUp();
        /* some code that initializes _repository */
    }

这看起来很丑陋。如果它是一个构造函数,我就不需要这样做。

我可以使用“模板方法”模式,具体如下:

public void MyBaseTest
{
    abstract void SetUp();

    [SetUp]
    public void BaseSetUp()
    {
        /* base initialization */
        SetUp(); // virtual call
    }
}

我也不太喜欢这个。

当他们的测试类需要SetUp,并且它们派生自另一个也需要SetUp的类时,您该怎么办?

5个回答

9

你必须直接调用该方法。

   [SetUp]
   public void DerivedSetUp()
   {
      base.BaseSetUp();
      // Do something else
   }

编辑:我没有尝试过,但或许可以使用部分方法。不过我更喜欢上面的方法。

编辑2:我刚刚尝试使用部分方法,但它没有起作用。即使起作用了,我认为调用基类仍然更容易。


部分方法吗?因为SetUp被装饰了一个属性,我不确定还有其他太多的方法可以做到这一点。 - Iain Holder
哦,没想到还有局部方法。这是一个有趣的方法。 - Roger Lipscombe
我不知道部分类方法是否可行。它们是私有的,无法被覆盖...http://msdn.microsoft.com/en-us/library/wa80x488.aspx - Jason Punyon
@JPunyon - 我认为你是对的。我刚刚在一个 spike 上尝试了一下。即使它们能够工作,我认为直接调用基本方法仍然更容易和更清晰。 - Iain Holder

3
您已经明确了基类。鉴于NUnit使用[Setup]属性来标记测试设置,我认为这对于NUnit来说是“正确的”做法,因为它遵循通常的语言规则。
当然,NUnit可以搜索基类,并自动调用其设置功能,但我认为这对大多数人来说会相当令人惊讶。
然而,至少有一个单元测试框架使用构造函数进行设置:xUnit.Net。在这里,基类设置将自动调用,因为这是C#中构造函数的行为方式。
(注意,虽然xUnit.Net建议不再使用测试设置。)

1

看起来你想要在任何测试开始之前只运行一次设置,而不是在每个测试运行之前都运行一次。注释[SetUp]使得该方法在运行您的夹具中的每个测试之前运行一次。[SetUp]不会被继承。

你想要使用的注释是[TestFixtureSetUp],它仅在夹具中的任何测试运行之前运行一次。这是按照你所期望的方式继承的。 :)

请参阅 TextFixtureSetUp文档


1
不行,我想要在每个测试运行之前执行此设置。 - Roger Lipscombe

0
我在TDD FireStarter中学到的一种方法是,在基类中使用设置方法,然后在基类中有一个名为observe的虚拟方法。在设置方法的末尾调用此方法。
然后,您需要在从基类派生的新类中覆盖observe方法。在这种情况下的技巧是,您希望执行基类的Setup方法,而子类没有Setup方法。原因是您在observe方法中编写的代码仅限于子测试类所需的其他内容。
这种方法对我很有效,但其中一个问题是测试运行程序将要执行基类测试。因此,如果有任何测试,我会将它们从基类移动到从基类派生的新类中。

这就是我在问题中提到的“模板方法”模式。虽然很高兴知道一些阵营推荐它。 - Roger Lipscombe

-1

以下代码在MbUnit中可行。在NUnit中也可能可行。

[TestFixture]
public abstract class Base {
    [SetUp]
    public virtual void SetUp() {
        //Some stuff.
    }
}

public class Derived : Base {
    public override void SetUp() {
        base.SetUp();
        //Some more stuff.
    }
    [Test]
    public virtual void Object_WhenInACertainState_WhenAMethodIsCalled_Throws() {
        //Create and set state on the object.
        //Call the method.
        //Assert the method threw.
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接