Search code examples
c#xunit

How can I pass values to xUnit tests that accept a nullable decimal?


One of my unit tests has this signature:

public void FooWithFilter(string fooId, decimal? amount)

When I test it with null, it works:

[InlineData("123", null)]

But if I use an actual value, such as:

[InlineData("123", 610)]

I get an error:

System.ArgumentException Object of type 'System.Int32' cannot be 
converted to type 'System.Nullable`1[System.Decimal]'.

I tried using 610M as the attribute value, but that's not allowed as an attribute value:

An attribute argument must be a constant expression, type of expression
or array creation expression of an attribute parameter type.

Is there a way to use a nullable decimal here?


Solution

  • As indicated in the comments, you can't use a decimal here because decimal is not one of the types that's allowed in attribute parameter values.

    However, xUnit provides a more flexible way to pass parameter values to test methods, using ClassData:

    [Theory]
    [ClassData(typeof(FooDataGenerator))]
    public void FooWithFilter(string fooId, decimal? amount)
    

    To use this, you simply need to define a class that extends IEnumerable<object[]> and produces the input values you want:

    public class FooDataGenerator : IEnumerable<object[]>
    {
        private readonly List<object[]> _data = new List<object[]>
        {
            new object[] {"123", null},
            new object[] {"123", 610M}
        };
    
        public IEnumerator<object[]> GetEnumerator() => _data.GetEnumerator();
    
        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
    }
    

    Some further references on the various ways of passing values to xUnit tests:
    Creating Parameterised tests in xUnit
    xUnit Theory: Working With InlineData, MemberData, ClassData