xUnit.net
testing framework
global setup
teardown
unit testing

xUnit.net Global setup teardown?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

xUnit.net does not have a single magic hook called "global setup" in the way some older test frameworks do. Instead, it gives you a few fixture patterns that match different scopes, so the right answer depends on whether you need per-test, per-class, per-collection, or assembly-wide initialization.

The xUnit Lifecycle Model

The first thing to understand is that xUnit encourages test isolation. A new instance of the test class is created for each test, so constructor logic acts like per-test setup and Dispose acts like per-test teardown.

csharp
1using System;
2using Xunit;
3
4public sealed class CalculatorTests : IDisposable
5{
6    public CalculatorTests()
7    {
8        Console.WriteLine("Runs before each test");
9    }
10
11    [Fact]
12    public void Adds_numbers()
13    {
14        Assert.Equal(4, 2 + 2);
15    }
16
17    public void Dispose()
18    {
19        Console.WriteLine("Runs after each test");
20    }
21}

That pattern is the default and should be your first choice when setup is cheap.

Sharing State Across Tests with Fixtures

When setup is expensive, such as starting a container or creating a database, xUnit fixtures let you share that work.

Class Fixtures

A class fixture is created once for a test class and shared by all tests in that class.

csharp
1using System;
2using Xunit;
3
4public sealed class DatabaseFixture : IDisposable
5{
6    public string ConnectionString { get; } =
7        "Server=(localdb)\\MSSQLLocalDB;Database=SampleTests;";
8
9    public void Dispose()
10    {
11        Console.WriteLine("Clean up shared database resources");
12    }
13}
14
15public sealed class RepositoryTests : IClassFixture<DatabaseFixture>
16{
17    private readonly DatabaseFixture fixture;
18
19    public RepositoryTests(DatabaseFixture fixture)
20    {
21        this.fixture = fixture;
22    }
23
24    [Fact]
25    public void Connection_string_is_available()
26    {
27        Assert.Contains("Database=SampleTests", fixture.ConnectionString);
28    }
29}

Use this when one test class owns the shared setup.

Collection Fixtures

A collection fixture is shared across multiple test classes. That is the closest option in xUnit v2 to "global setup" for a related group of tests.

csharp
1using Xunit;
2
3[CollectionDefinition("Database collection")]
4public sealed class DatabaseCollection : ICollectionFixture<DatabaseFixture>
5{
6}
7
8[Collection("Database collection")]
9public sealed class CustomerTests
10{
11    private readonly DatabaseFixture fixture;
12
13    public CustomerTests(DatabaseFixture fixture)
14    {
15        this.fixture = fixture;
16    }
17
18    [Fact]
19    public void Uses_shared_fixture()
20    {
21        Assert.NotNull(fixture.ConnectionString);
22    }
23}

This keeps setup centralized while still limiting the scope to a known set of tests.

Assembly-Wide Setup

Assembly fixtures were introduced in xUnit.net v3. If you are on v3, you can share one fixture across the entire test assembly.

csharp
1using System;
2using Xunit;
3
4public sealed class AssemblyFixture : IDisposable
5{
6    public string EnvironmentName { get; } = "IntegrationTests";
7
8    public void Dispose()
9    {
10        Console.WriteLine("Assembly cleanup");
11    }
12}
13
14[assembly: AssemblyFixture(typeof(AssemblyFixture))]

This is true assembly-wide setup and teardown, but it is version-specific. If you are using xUnit v2, this exact feature is not available.

Choosing the Right Scope

Pick the smallest scope that solves the problem. If you only need a fresh object per test, use the constructor and Dispose. If an expensive shared dependency belongs to one class, use IClassFixture. If several classes need the same dependency, use ICollectionFixture. Reserve assembly-wide state for resources that are genuinely global and safe to share.

Smaller scopes reduce coupling and make parallel test execution safer. Large shared fixtures can speed tests up, but they also make isolation failures harder to debug.

Common Pitfalls

  • Looking for a [SetUp] or [TearDown] attribute because another framework uses that style. xUnit is intentionally different.
  • Assuming there is one built-in global setup API in every xUnit version. Assembly fixtures are an xUnit v3 feature.
  • Sharing mutable state through fixtures and then getting flaky tests when execution order changes.
  • Doing too much work in the test class constructor when the work should really be shared in a fixture.
  • Forgetting cleanup in Dispose, especially for files, sockets, containers, and database connections.

Summary

  • xUnit uses constructors and Dispose for per-test setup and teardown.
  • 'IClassFixture shares setup across one test class.'
  • 'ICollectionFixture shares setup across multiple related test classes.'
  • Assembly-wide fixtures exist in xUnit.net v3, not in every earlier version.
  • Choose the smallest fixture scope that keeps tests isolated and predictable.

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.