xUnit [Fact] vs [Theory]: InlineData, MemberData and TheoryData in C#
[Fact]: a test without parameters, one scenario.
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); } |