NUnit 是否在每次测试之间重新实例化标记为 TestFixtures 的类?

Guy*_*ean 5 c# nunit nsubstitute

我有一个 TestFixture 标记的类,它是对名为“HideCurrentTitleBarMessageTask”的类的功能进行单元测试。

在这个类中,我使用一个替代来模拟 [Setup] 方法中的一个接口,并且在测试类中的一些测试中,我设置了一个来自模拟接口成员的返回结果。

[TestFixture]
public class TestClass_A {

    private ITitleBarMessageModel model;
    private ITitleBarMessage message;
    private HideCurrentTitleBarMessageTask task;
    private bool taskCompleteFired;


    [SetUp]
    public void SetUp() {
        taskCompleteFired = false;
        model = Substitute.For<ITitleBarMessageModel>();
        message = Substitute.For<ITitleBarMessage>();
        //model.currentlyDisplayedMessage = null;
        task = new HideCurrentTitleBarMessageTask();
        task.Init(model);
        task.Completed += (t) => { taskCompleteFired = true; };
    }

    [Test]
    public void Test_A() {
        task.Execute();
        Assert.That(taskCompleteFired, Is.True);
    }

    [Test]
    public void Test_B() {
        model.currentlyDisplayedMessage.Returns(message);
        task.Execute();
        message.Received(1).Hide();
        Assert.That(taskCompleteFired, Is.False);
    }
}
Run Code Online (Sandbox Code Playgroud)

HideCurrentTitleBarMessageTask 的 Execute 函数如下所示

public override void Execute() {
        if (model.currentlyDisplayedMessage != null) {
            //Some irrelevant stuff
        } else {
            Completed(this);
        }
}
Run Code Online (Sandbox Code Playgroud)

注意,只有Test_B,做我的设置有一个返回值model.currentlyDisplayedMessage

如果我在 Test_A 的第 1 行断点,我会在调试器中看到model.currentlyDisplayedMessage不为空,但实际上已分配。不应该的时候。即使可以推测,方法SetUp之前被调用,并且该行

model = Substitute.For<ITitleBarMessageModel>();
Run Code Online (Sandbox Code Playgroud)

被执行,有效地将一个新的模拟实例重新分配给模型。这会导致 Test_A 失败。

现在,注意注释掉的行

//model.curentlyDisplayedMessage = null;
Run Code Online (Sandbox Code Playgroud)

在设置方法中。取消注释,通过将模型中的引用显式设置为空来解决问题。(我还假设在 [TearDown] 标记的方法中可以实现相同的结果)。

NUnit 不会清除 TestClass 并在两次测试之间从头开始吗?

如果没有,谁能告诉我为什么我打电话给

model = Substitute.For<ITitleBarMessageModel>();
Run Code Online (Sandbox Code Playgroud)

在 SetUp() 方法中没有为我提供模型的干净模拟实例,以开始我的测试?

Cha*_*lie 7

不,NUnit 不会为每个测试用例创建一个新的夹具类实例。创建单个实例,然后为每个测试重用。这与其他一些测试框架不同,但它是 NUnit 一直工作的方式(自 2000 年以来)。

这意味着您必须小心使用对象状态的方式。1.尽量少用state。2.使用SetUp进行初始化,使用TearDown进行清理。

根据@David 的评论... NSubstitute 将自动替换返回接口的成员。请参阅递归模拟。我认为这解释了为什么 model.currentlyDisplayedMessage 是为新替换的模型初始化的。