Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to have a SetUpFixture that runs once per class instead of once per namespace?

Scenario
First of all, I'm new to testing - so please bear with me. Inside of my test project, there is a Controllers folder. The Controllers folder may contain a ControllerATest.cs, ControllerBTest.cs, and ControllerCTest.cs. Because my namespace aligns with my folder structure, they all share the namespace MyProject.Tests.Controllers.

From what I've read in the NUnit SetUpFixture Documentation, a [SetUpFixture] inside this namespace will run once for the entire namespace. That is, if I run all of my controller tests at once - the SetUpFixture will be executed only once.

Problem
As I said, each controller test shares a namespace. SetUpFixtures apply to the entire namespace. What if I want each controller to have their own SetUpFixture? This is a problem when SetUpFixtures apply to entire namespaces. What I want is something that executes once, and not per-test. One of the things I do inside my SetUpFixture's SetUp is instantiate a controller. Sure, I could instantiate all 3 controllers in the SetUpFixture, but this seems ugly when maybe I am only testing ControllerC. That really doesn't seem clean. Therefore, I would like a SetUpFixture that applies only to the class it appears in, such as ControllerCTests.

From what I've read, this specific functionality seems to be impossible with NUnit. And if it's not possible with NUnit, that makes me think it's not a common scenario. And if it's not a common scenario, I am doing something wrong. My question is, what? Maybe my testing structure is off and it needs to change. Or maybe it is possible with NUnit?

Code
An example of my desired structure:

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()         {             //         }     } } }     

Things I've Tried

  • Moving each .cs file into its own folder, so they have different namespaces. Technically this solves the problem, it just seems a little ugly to have a bunch of subfolders with only 1 item in each of them. Ugly, and will no longer match my parent project's structure which I was going for. But - maybe this is the way to go.
  • Not instantiating my controller in the SetUpFixture SetUp, and instead doing it in the TestFixture SetUp so that a new one gets instantiated for every test (ex: 5 tests = 5 separate instances) instead of once per class or namespace. Though it seems like if I can get away with only creating 1 instance, I should.

Suggestions?

like image 362
EF0 Avatar asked Apr 18 '14 16:04

EF0


Video Answer


2 Answers

For NUnit 3.4.1 and later, use OneTimeSetUp:

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

By the way, TestFixtureSetUp has been deprecated.

like image 129
Tyler Liu Avatar answered Sep 21 '22 04:09

Tyler Liu


Use a TestFixtureSetUpAttribute on a method in your Controller class:

[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()     {         // ...     } } 

From the documentation:

This attribute is used inside a TestFixture to provide a single set of functions that are performed once prior to executing any of the tests in the fixture.

Here, "TestFixture" is synonymous with class.

like image 37
Patrick Quirk Avatar answered Sep 22 '22 04:09

Patrick Quirk