What it is
xUnit.net is the most widely used .NET testing framework, with a minimal API, parallel execution by default and constructor-based test setup.
[Fact] marks a parameterless test, [Theory] with data attributes marks a parameterised one. Each test class is instantiated fresh per test, so state cannot leak.
Installation
dotnet new xunit -n MyTestsGetting started
The smallest useful thing you can do with it, and what each part means.
csharp
public class SlugifyTests
{
private readonly Slugifier _sut = new(); // fresh for every test
[Fact]
public void Handles_empty_input() =>
Assert.Equal(string.Empty, _sut.Slugify(""));
[Theory]
[InlineData("Hello World", "hello-world")]
[InlineData("C# & Go!", "c-go")]
[InlineData(" spaced ", "spaced")]
public void Slugifies(string input, string expected) =>
Assert.Equal(expected, _sut.Slugify(input));
}Advanced usage
Where the library earns its place over a simpler alternative.
csharp
public class DatabaseFixture : IAsyncLifetime
{
public string ConnectionString { get; private set; } = default!;
public async Task InitializeAsync() => ConnectionString = await StartContainerAsync();
public async Task DisposeAsync() => await StopContainerAsync();
}
[CollectionDefinition("db")]
public class DbCollection : ICollectionFixture<DatabaseFixture> { }
[Collection("db")] // shares one fixture across the collection
public class BookRepositoryTests
{
private readonly DatabaseFixture _fixture;
public BookRepositoryTests(DatabaseFixture fixture) => _fixture = fixture;
}Errors and fixes
The failures you are most likely to hit, and what actually resolves them.
- Tests interfere with each other
- Something is static or shared. Test classes are isolated per test; static state is not.
- Async tests pass without asserting
- The test returns void instead of Task, so the runner does not await it. Return Task from async tests.
Best practices
- Use the constructor for setup and IDisposable for teardown; xUnit has no [SetUp] by design.
- Prefer [Theory] with InlineData over near-duplicate test methods.
- Use collection fixtures for expensive shared resources, and be aware they disable parallelism within the collection.
- Pair with FluentAssertions for failure messages that explain what differed.
Background
Why it exists, and what it was reacting to.
Written by the original NUnit authors, xUnit removed features they had come to regard as mistakes — notably setup and teardown attributes, replaced by ordinary constructors and IDisposable.
