有没有办法让每个类运行一次SetUpFixture而不是每个名称空间运行一次?

EF0*_*EF0 22 c# nunit unit-testing asp.net-mvc-5

场景
首先,我是新手测试 - 所以请耐心等待.在我的测试项目中,有一个Controllers文件夹.Controllers文件夹可能包含ControllerATest.cs,ControllerBTest.cs和ControllerCTest.cs.因为我的命名空间与我的文件夹结构一致,所以它们共享命名空间MyProject.Tests.Controllers.

根据我在NUnit SetUpFixture文档中读到的内容,此命名空间内的[SetUpFixture]将为整个命名空间运行一次.也就是说,如果我一次运行所有控制器测试 - SetUpFixture将只执行一次.

问题
正如我所说,每个控制器测试共享一个名称空间.SetUpFixtures适用于整个命名空间.如果我希望每个控制器都有自己 SetUpFixture怎么办?当SetUpFixtures应用于整个名称空间时,这是一个问题.我想要的是一次执行,而不是每次测试.我在SetUpFixture的SetUp中做的一件事就是实例化一个控制器.当然,我可以在SetUpFixture中实例化所有3个控制器,但是当我可能只测试ControllerC时,这看起来很难看.这真的不干净.因此,我想其施加SetUpFixture 只有它出现在类,如ControllerCTests.

根据我的阅读,NUnit似乎不可能实现这一特定功能.如果NUnit无法实现,那么我认为这不是常见的情况.如果这不是常见的情况,我做错了.我的问题是,什么?也许我的测试结构已关闭,需要更改.或者,也许这可能的NUnit的?

代码
我想要的结构的一个例子:

namespace MyProject.Tests.Controllers
{
public class ControllerATests
{
    private static IMyProjectRepository _fakeRepository;
    private static ControllerA _controllerA;

    [SetUpFixture]
    public class before_tests_run
    {
        [SetUp]
        public void ControllerASetup()
        {
            _fakeRepository = FakeRepository.Create();

            _controllerA = new ControllerA(_fakeRepository);
        }
    }

    [TestFixture]
    public class when_ControllerA_index_get_action_executes
    {
        [Test]
        public void it_does_something()
        {
            //
        }

        [Test]
        public void it_does_something_else()
        {
            //
        }
    }
}

public class ControllerBTests
{
    private static IMyProjectRepository _fakeRepository;
    private static ControllerB _controllerB;

    [SetUpFixture]
    public class before_tests_run
    {
        [SetUp]
        public void ControllerBSetup()
        {
            _fakeRepository = FakeRepository.Create();

            _controllerB = new ControllerB(_fakeRepository);
        }
    }

    [TestFixture]
    public class when_ControllerB_index_get_action_executes
    {
        [Test]
        public void it_does_something()
        {
            //
        }

        [Test]
        public void it_does_something_else()
        {
            //
        }
    }
}
}    
Run Code Online (Sandbox Code Playgroud)

我试过的事情

  • 将每个.cs文件移动到其自己的文件夹中,因此它们具有不同的命名空间.从技术上讲,这解决了这个问题,拥有一堆只有1个项目的子文件夹似乎有点难看.丑陋,将不再符合我的父项目的结构.但是 - 也许这是要走的路.
  • 不在SetUpFixture SetUp中实例化我的控制器,而是在TestFixture SetUp中执行它,以便为每个测试实例化一个新的实例(例如:5个测试= 5个单独的实例),而不是每个类或命名空间一次.虽然看起来我只能创建1个实例,但我应该这样做.

建议?

Tyl*_*ong 46

对于NUnit 3.4.1及更高版本,请使用OneTimeSetUp:

[TestFixture]
public class MyTest
{
    [OneTimeSetUp]
    public void Setup()
    {
        // one time setup code for this class
    }
}
Run Code Online (Sandbox Code Playgroud)

顺便说一句,TestFixtureSetUp已被弃用.


Pat*_*irk 20

TestFixtureSetUpAttribute在Controller类中使用on方法:

[TestFixture]
public class when_ControllerA_index_get_action_executes
{
    [TestFixtureSetUp]
    public void FixtureSetUp()
    {
        // this code runs once no matter how many tests are in this class
    }

    [Test]
    public void it_does_something()
    {
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

从文档:

此属性在TestFixture内部使用,以提供在执行夹具中的任何测试之前执行一次的单个函数集.

在这里,"TestFixture"是同义词class.

  • 如果您使用的是Nunit 3.0或更高版本,请查看以下Tyler的答案. (7认同)