SyntaxStudy
Sign Up
C# Unit Testing with xUnit
C# Beginner 1 min read

Unit Testing with xUnit

xUnit is the most popular unit testing framework for .NET, favoured by the .NET team itself. Tests are plain classes with no base class requirement. A method decorated with `[Fact]` is a single test case; `[Theory]` combined with `[InlineData]` or `[MemberData]` creates parameterised tests that run with multiple input sets. The Arrange-Act-Assert (AAA) pattern is the standard structure for a unit test: set up prerequisites, invoke the code under test, then verify the outcome. xUnit's `Assert` class provides assertions for equality, nullability, exceptions, collections, and type checking. `IDisposable` and `IAsyncLifetime` interfaces handle per-test setup and teardown. Shared context (e.g. a database container) is handled through class fixtures (`IClassFixture`) and collection fixtures (`ICollectionFixture`), keeping expensive initialisation to a minimum.
Example
// xUnit unit tests with Fact, Theory, and Arrange-Act-Assert

using Xunit;

// Class under test
public static class Calculator
{
    public static int  Add(int a, int b)      => a + b;
    public static int  Subtract(int a, int b) => a - b;
    public static double Divide(double a, double b)
    {
        if (b == 0) throw new DivideByZeroException();
        return a / b;
    }
    public static IEnumerable<int> Range(int start, int count)
        => Enumerable.Range(start, count);
}

public class CalculatorTests
{
    // [Fact] — single test case
    [Fact]
    public void Add_TwoPositiveNumbers_ReturnsSum()
    {
        // Arrange
        int a = 3, b = 4;

        // Act
        int result = Calculator.Add(a, b);

        // Assert
        Assert.Equal(7, result);
    }

    // [Theory] — parameterised test
    [Theory]
    [InlineData(10,  2,   5.0)]
    [InlineData(9,   3,   3.0)]
    [InlineData(-6,  2,  -3.0)]
    public void Divide_ValidInputs_ReturnsCorrectQuotient(double a, double b, double expected)
    {
        double result = Calculator.Divide(a, b);
        Assert.Equal(expected, result, precision: 10);
    }

    [Fact]
    public void Divide_ByZero_ThrowsDivideByZeroException()
    {
        Assert.Throws<DivideByZeroException>(() => Calculator.Divide(5, 0));
    }

    [Fact]
    public void Range_ValidInput_ReturnsCorrectSequence()
    {
        IEnumerable<int> result = Calculator.Range(1, 5);
        Assert.Equal(new[] { 1, 2, 3, 4, 5 }, result);
    }

    [Fact]
    public void Subtract_ResultIsNegative_ReturnsNegativeValue()
    {
        int result = Calculator.Subtract(3, 10);
        Assert.True(result < 0);
        Assert.Equal(-7, result);
    }
}