Search code examples
c#.netnunit

NUnit Unit Tests + TestContainers = global `OneTimeSetup` and `OneTimeTearDown`


I'm trying to make good usage of TestContainers with NUnit to run my .NET tests. I have two test cases that, once started, get a created MongoDb container, connect to it, do their job and then dipose the given container.

As you can see on the picture below, the current execution time is ~9s, with both tests taking ~5s and ~4s, respectively.

enter image description here

Each of those tests are inhereting from a base class, which has a OneTimeSetUp and OneTimeTearDown implementation that take care of the container's lifetime:

[OneTimeSetUp]
public async Task OneTimeSetup()
{
    _testContainer = new MongoDbBuilder().Build();
    await _testContainer.StartAsync();

    _client = new MongoClient(_testContainer.GetConnectionString());
    Database = _client.GetDatabase("test");
}

[OneTimeTearDown]
public async Task OneTimeTeardown() => await _testContainer.DisposeAsync();

As you can see, for each tests, the same setup and teardown is being run, resulting a contaienr being created and destroyed in each test.

What I want to achieve is:

Global Setup <==== spin the container here
Test1 Setup <---- uses the newly created container
Test1 Run
Test1 Teardown

Test2 Setup  <---- uses the same container
Test2 Run
Test2 Teardown

Global Teardown <==== destroys the container here

Is there a way I can achieve that with NUnit? Thank y'all!


Solution

  • Nunit does not like derived classed for startup and tear down but you could create another class with in the same names space that is TestFixture setup class.. Below is an example

      namespace ClassLibrary1
      {
    
    [SetUpFixture]
    public  class TestFixtureSetup
    {
        [OneTimeSetUp]
        public void TestSetup()
        {
            int x = 10;
           
        }
    
        [OneTimeTearDown]
        public void TestTeardown()
        {
            int x = 10;
        }
    }
    public class DaughterTest 
    {
        [Test]
        public void Test1()
        {
            Console.WriteLine("Daughter.Test1");
        }
    }
    
    public class SonTest
    {
        [Test]
        public  void Test1()
        {
            Console.WriteLine("Son.Test1");
        }
     }
    }
    

    To see the example run put break points in each function to check the order.