如何将值传递给接受可为空小数的 xUnit 测试?

问题描述 投票:0回答:4

我的一个单元测试有这个签名:

public void FooWithFilter(string fooId, decimal? amount)

当我用 null 测试它时,它有效:

[InlineData("123", null)]

但是如果我使用实际值,例如:

[InlineData("123", 610)]

我收到错误:

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

我尝试使用

610M
作为属性值,但不允许作为属性值:

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

这里有没有办法使用可为空的小数?

c# xunit
4个回答
14
投票

如注释中所示,您不能在此处使用

decimal
,因为
decimal
不是属性参数值中允许的类型之一。

但是,xUnit 提供了一种更灵活的方式将参数值传递给测试方法,使用

ClassData
:

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

要使用它,您只需定义一个扩展

IEnumerable<object[]>
的类并生成您想要的输入值:

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();
}

有关向 xUnit 测试传递值的各种方法的一些进一步参考:
在 xUnit 中创建参数化测试
xUnit 理论:使用 InlineData、MemberData、ClassData


7
投票

解决此问题的一个简单方法是将参数设置为双倍?并将它们转换为十进制?像这样

[Theory]
        [InlineData(1200, 1150, 50, 100)]
        [InlineData(1200.50, 1200.50, 0, 0)]
        [InlineData(1250.50, 1150, 0, 100.50)]
        [InlineData(1150, 1150, null, null)]
        [InlineData(0, null, null, null)]
        [InlineData(-50, null, 50, null)]
        [InlineData(50, null, null, 50)]

        public void SubTotal(double valorEsperado, double? valorTotal, double? valorFrete, double? valorDesconto) =>
            Assert.Equal((decimal)valorEsperado, PedidoBuilderTest.New
                                            .AtribuirValores((decimal?)valorTotal, (decimal?)valorFrete, (decimal?)valorDesconto)
                                            .Build().SubTotal);

7
投票

除了 JLRishe 的答案之外,我建议从

TheoryData
或其通用对应方
TheoryData<>
继承,以便我们获得强类型测试数据和更清晰的代码。我发现文档在这方面有些薄弱。

[Theory]
[ClassData(typeof(FooDataGenerator))]
public void FooWithFilter(string fooId, decimal? expected)
{
    // Arrange // Act // Assert
}

public class FooDataGenerator : TheoryData<string, decimal?>
{
    public FooDataGenerator()
    {
        this.Add("987", null);
        this.Add("123", 610m);
        // ...
    }
}

0
投票

如果您不想创建新课程,还有

MemberData

例如:

[Theory]
[MemberData(nameof(DoSomethingTestData))]
public void Should_Do_Something(string someStr, decimal? someDecimal, decimal expectedDecimal)
{
    // Arrange
    // Act
    // Assert
}

public static IEnumerable<object[]> DoSomethingTestData()
{
    var allData = new List<object[]>
    {
        new object[] { "SomeString", 1M, 2M },
        new object[] { "SomeOtherString", null, 1M } // etc.
    };

    return allData;
}
© www.soinside.com 2019 - 2024. All rights reserved.