xUnit [Fact] vs [Theory]: InlineData, MemberData and TheoryData in C#

xUnit Testing & CI/CD in .NET November 13, 2026 csharp

[Fact]: a test without parameters, one scenario.

csharp
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// ======================================================================
// Q: [Fact] vs [Theory]? How do you pass test data?
//
// [Fact]: a test without parameters, one scenario. [Theory]: the same test with
// multiple data sets. Each data set shows up as a separate test.
// There is also [ClassData(typeof(...))] for data in a separate class.
// InlineData only accepts compile-time constants (no decimal, no objects): hence
// TheoryData.
// ======================================================================

[Theory]
[InlineData(0)]
[InlineData(-1)]
[InlineData(10_001)]
public void AddLine_rejects_invalid_quantity(int quantity)
{
    var order = new OrderBuilder().Build();
    Assert.Throws<DomainException>(() => order.AddLine("PIP-100", quantity, Money.Eur(10m)));
}

// Complex data: TheoryData<T> (strongly typed) with MemberData
public static TheoryData<string, decimal, string, decimal> ShippingCases => new()
{
    { "dhl", 2.5m, "DE", 8.90m },
    { "dhl", 2.5m, "GR", 16.40m },     // +7.50 outside Germany
    { "ups", 1.0m, "DE", 8.40m },
};

[Theory]
[MemberData(nameof(ShippingCases))]
public void Calculates_shipping_cost(string carrier, decimal kg, string country, decimal expected)
{
    var calculator = factory.Create(carrier);
    Assert.Equal(expected, calculator.Calculate(new ShipmentRequest(kg, country)).Amount);
}