Search code examples
c#.netxunit.net

xUnit.net: Global setup + teardown?


This question is about the unit testing framework xUnit.net.

I need to run some code before any test is executed, and also some code after all tests are done. I thought there should be some kind of attribute or marker interface to indicate the global initialization and termination code, but couldn't find them.

Alternatively, if I invoke xUnit programmatically, I can also achieve what I want with the following code:

static void Main()
{
    try
    {
        MyGlobalSetup();
        RunAllTests();  // What goes into this method?
    }
    finally
    {
        MyGlobalTeardown();
    }
}

Can anyone provide me a hint about how to declaratively or programmatically run some global setup/teardown code?


Solution

  • As far as I know, xUnit does not have a global initialization/teardown extension point. However, it is easy to create one. Just create a base test class that implements IDisposable and do your initialization in the constructor and your teardown in the IDisposable.Dispose method. This would look like this:

    public abstract class TestsBase : IDisposable
    {
        protected TestsBase()
        {
            // Do "global" initialization here; Called before every test method.
        }
    
        public void Dispose()
        {
            // Do "global" teardown here; Called after every test method.
        }
    }
    
    public class DummyTests : TestsBase
    {
        // Add test methods
    }
    

    However, the base class setup and teardown code will be executed for each call. This might not be what you want, as it is not very efficient. A more optimized version would use the IClassFixture<T> interface to ensure that the global initialization/teardown functionality is only called once. For this version, you don't extends a base class from your test class but implement the IClassFixture<T> interface where T refers to your fixture class:

    using Xunit;
    
    public class TestsFixture : IDisposable
    {
        public TestsFixture ()
        {
            // Do "global" initialization here; Only called once.
        }
    
        public void Dispose()
        {
            // Do "global" teardown here; Only called once.
        }
    }
    
    public class DummyTests : IClassFixture<TestsFixture>
    {
        public DummyTests(TestsFixture data)
        {
        }
    }
    

    This will result in the constructor of TestsFixture only being run once for every class under test. It thus depends on what you want exactly to choose between the two methods.