CodeBlanks Logo Icon CodeBlanks

[Fact]

C# course · Advanced · Lesson 68/83

Learn to write test methods with [Fact].

The [Fact] attribute

[Fact] declares that a method is a test. It takes no parameters and returns nothing; it checks a single scenario. The runner collects all methods marked this way and runs them in turn.

A good [Fact] test focuses on one behavior: one input, one expected result. If it checks multiple things, a failure leaves the broken piece unclear. So TestAddReturnsFive and TestAddNegative are separate methods.

Test naming and structure

Test names should describe behavior: TestAddReturnsFive, ShouldThrowOnNegative, or Add_TwoPlusThree_ReturnsFive. These names reveal the failure at a glance.

Each test must be independent: no test should depend on another's data or order. That is why tests share setup in a Setup method (in xUnit, the constructor); each test starts with its own instance.

Exercise Write two [Fact] tests

Define FactAttribute and a static Assert class (Assert.Equal<T> throws Exception on inequality). Add both Add(int, int) and Subtract(int, int) to Calculator. Write two [Fact] methods in CalculatorTests: TestAddReturnsFive calls Assert.Equal(5, Calculator.Add(2, 3)); TestSubtractReturnsOne calls Assert.Equal(1, Calculator.Subtract(3, 2)). In Main, call both and print "Test passed: Add and Subtract" on success.

Show example solution
Attribute { } and static class Assert { public static void Equal<T>(T expected, T actual) { if (!EqualityComparer<T>.Default.Equals(expected, actual)) throw new Exception($"Expected {expected}"); } }. Write class Calculator { public static int Add(int a, int b) => a + b; public static int Subtract(int a, int b) => a - b; }. Write class CalculatorTests { [Fact] public void TestAddReturnsFive() { Assert.Equal(5, Calculator.Add(2, 3)); } [Fact] public void TestSubtractReturnsOne() { Assert.Equal(1, Calculator.Subtract(3, 2)); } }. In Main: var t = new CalculatorTests(); t.TestAddReturnsFive(); t.TestSubtractReturnsOne(); Console.WriteLine("Test passed: Add and Subtract");
Example solution:
using System;

class FactAttribute : Attribute { }

static class Assert
{
    public static void Equal<T>(T expected, T actual)
    {
        if (!EqualityComparer<T>.Default.Equals(expected, actual))
            throw new Exception($"Expected {expected}, got {actual}");
    }
}

class Calculator
{
    public static int Add(int a, int b) => a + b;
    public static int Subtract(int a, int b) => a - b;
}

class CalculatorTests
{
    [Fact]
    public void TestAddReturnsFive()
    {
        Assert.Equal(5, Calculator.Add(2, 3));
    }

    [Fact]
    public void TestSubtractReturnsOne()
    {
        Assert.Equal(1, Calculator.Subtract(3, 2));
    }
}

class Program
{
    static void Main()
    {
        var tests = new CalculatorTests();
        tests.TestAddReturnsFive();
        tests.TestSubtractReturnsOne();
        Console.WriteLine("Test passed: Add and Subtract");
    }
}

Test yourself

  1. Which methods does [Fact] mark?

    • Only static methods
    • Parameterless void test methods
    • Async methods only
    • Only private methods
    Show answer

    Parameterless void test methods — Correct. [Fact] marks parameterless void test methods.

  2. Complete the test method

    public void ____() { Assert.Equal(4, Calculator.Add(2, 2)); }
    Show answer
    public void TestAddTwoPlusTwo() { Assert.Equal(4, Calculator.Add(2, 2)); }
  3. What should a [Fact] method do?

    • Test multiple classes at once
    • Write to a database
    • Read user input
    • Test a single behavior
    Show answer

    Test a single behavior — Correct. [Fact] tests one behavior; it does not mix concerns.

All lessons in Advanced