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

Unit Testing with NUnit

NUnit is the oldest major .NET testing framework, with roots in JUnit. It uses `[TestFixture]` to mark a test class and `[Test]` to mark test methods. `[SetUp]` and `[TearDown]` run before and after each test; `[OneTimeSetUp]` and `[OneTimeTearDown]` run once for the entire fixture. NUnit's constraint model (`Assert.That(actual, Is.EqualTo(expected))`) provides a fluent, readable assertion syntax. It covers equality, ordering, string matching, collection contents, exception throwing, and more. NUnit's `TestCase` attribute is the equivalent of xUnit's `InlineData`. Both xUnit and NUnit integrate with `dotnet test` and all major IDEs (Visual Studio, Rider, VS Code with the Test Explorer extension). Test results are reported in the TRX or JUnit XML format and can be consumed by CI/CD platforms like GitHub Actions, Azure DevOps, and Jenkins.
Example
// NUnit tests — TestFixture, SetUp, TearDown, and constraint model

using NUnit.Framework;
using System.Collections.Generic;

[TestFixture]
public class ShoppingCartTests
{
    private ShoppingCart _cart = null!;

    [SetUp]
    public void BeforeEachTest()
    {
        _cart = new ShoppingCart();
    }

    [TearDown]
    public void AfterEachTest()
    {
        _cart.Clear();
    }

    [Test]
    public void AddItem_NewItem_IncreasesCount()
    {
        _cart.Add(new CartItem("Widget", 9.99m, 1));
        Assert.That(_cart.Count, Is.EqualTo(1));
    }

    [Test]
    public void Total_MultipleItems_SumsCorrectly()
    {
        _cart.Add(new CartItem("Widget", 10m, 2));
        _cart.Add(new CartItem("Gadget", 25m, 1));
        Assert.That(_cart.Total, Is.EqualTo(45m).Within(0.001m));
    }

    [TestCase(0,   0m)]
    [TestCase(1,  10m)]
    [TestCase(3,  30m)]
    public void Total_VaryingQuantities_CalculatesCorrectly(int qty, decimal expected)
    {
        _cart.Add(new CartItem("X", 10m, qty));
        Assert.That(_cart.Total, Is.EqualTo(expected));
    }

    [Test]
    public void Remove_ExistingItem_RemovesFromCart()
    {
        _cart.Add(new CartItem("Widget", 10m, 1));
        _cart.Remove("Widget");
        Assert.That(_cart.Count, Is.Zero);
    }

    [Test]
    public void Remove_NonExistentItem_ThrowsKeyNotFoundException()
    {
        Assert.That(() => _cart.Remove("Ghost"),
            Throws.TypeOf<KeyNotFoundException>());
    }
}

// Domain classes (would live in your main project)
record CartItem(string Name, decimal Price, int Qty);

class ShoppingCart
{
    private readonly List<CartItem> _items = new();
    public int     Count => _items.Count;
    public decimal Total => _items.Sum(i => i.Price * i.Qty);
    public void    Add(CartItem item) => _items.Add(item);
    public void    Clear()            => _items.Clear();
    public void    Remove(string name)
    {
        var item = _items.FirstOrDefault(i => i.Name == name)
            ?? throw new KeyNotFoundException(name);
        _items.Remove(item);
    }
}