为什么在[Test]之后而不是之前调用Nunit3 OneTimeSetUp()

为什么在[Test]之后而不是之前调用Nunit3 OneTimeSetUp(),nunit,nunit-3.0,nunit-console,Nunit,Nunit 3.0,Nunit Console,我用Nunit 2.6编写了单元测试,但计划升级到Nunit 3.6.1,但是我注意到Nunit 3.6.1有一个奇怪的问题(或者可能是我没有正确理解它)。问题出在OneTimeSetUp()上 在Nunit 2.6.3中,我有SetUpFixtureAttribute[SetUpFixture],在该SetUpAttribute[SetUp]中,它按照我的预期工作,流程是 SetUpFixture.Setup TestFixture.Setup 测试夹具 TestFixture.TearDow

我用Nunit 2.6编写了单元测试,但计划升级到Nunit 3.6.1,但是我注意到Nunit 3.6.1有一个奇怪的问题(或者可能是我没有正确理解它)。问题出在OneTimeSetUp()上

在Nunit 2.6.3中,我有SetUpFixtureAttribute[SetUpFixture],在该SetUpAttribute[SetUp]中,它按照我的预期工作,流程是

SetUpFixture.Setup

TestFixture.Setup

测试夹具

TestFixture.TearDown

TestFixture.Setup

测试夹具

TestFixture.TearDown

设置夹具。拆卸

当我升级到Nunit 3时,我将SetUpFixture中的SetUp()替换为OneTimeSetUp,在运行代码后,我得到了以下流程

TestFixture.Setup

测试夹具

TestFixture.TearDown

SetUpFixture.OneTimeSetUp

SetUpFixture.onetimeeardown

下面是我在我的机器上尝试的示例代码以及命令行输出

   [SetUpFixture]
    public class TestBase
    {
        [OneTimeSetUp]
        //[SetUp]
        public static void MyTestSetup()
        {
            Console.WriteLine(" ---------- Calling OneTimeSetUp ----------");

        }
    }


[TestFixture]
    class TestClass : TestBase
    {
        [Test]
        public void test()
        {
            Console.WriteLine("\n ....I'm inside TestClass.test() ....");
        }

    }
控制台输出

=> TestSample.TestClass.test

 ....I'm inside TestClass.test() ....
=> TestSample.TestClass
 ---------- Calling OneTimeSetUp ----------
=> TestSpecflow.TestBase
 ---------- Calling OneTimeSetUp ----------
有人能告诉我我在这里遗漏了什么吗?
我正在通过nunit控制台运行测试

问题是输出有误导性,并且不符合代码的执行顺序。因为NUnit 3支持并行执行,所以当该级别的测试执行完成时,它会捕获输出并在控制台上显示

在您的例子中,fixture设置包装测试,以便在测试之后完成执行,并在测试之后输出捕获的文本

如果调试测试,或者将
控制台.WriteLine
调用切换到立即输出的
TestContext.Progress.WriteLine
,您将看到代码按照预期的顺序执行

如果它不符合您期望的顺序,请查看名称空间。请记住,
[SetupFixture]
用于在命名空间级别进行设置。如果您的测试位于不同的命名空间中,则可能会以不同的顺序调用它们。如果要为所有测试设置,请将该类放在顶级命名空间中,或者如果有多个命名空间,则不要放在任何命名空间中

下面是一些测试代码

namespace NUnitFixtureSetup
{
    [SetUpFixture]
    public class SetupClass
    {
        [OneTimeSetUp]
        public void MyTestSetup()
        {
            TestContext.Progress.WriteLine("One time setup");
        }
    }

    [TestFixture]
    public class TestClass
    {
        [Test]
        public void TestMethod()
        {
            TestContext.Progress.WriteLine("Test Method");
        }
    }
}
下面是使用
nunit3 console.exe运行的输出

=> NUnitFixtureSetup.SetupClass
One time setup
=> NUnitFixtureSetup.TestClass.TestMethod
Test Method

Rob的答案是您遇到问题的根本原因,但是还有一个问题,它出现在您的代码中,尽管Rob的代码中没有

在代码中,您两次使用TestBase:作为SetUpFixture和TestFixture的基类

这意味着一次性设置方法将使用两次。。。在命名空间中的所有fixture之前一次,在从其继承的任何测试fixture之前一次。以这种方式使用SetUpFixture违背了它的目的,即在命名空间中的fixture之前,某些代码只运行一次

使用单独的类作为基类(如果需要)和设置夹具(如果需要)