为什么我们的测试方法参数中的类型实例化不完整 - AutoFixture with AutoData

Why do we have incomplete instantiation of types from the test method parameter - AutoFixture with AutoData

使用 Autofixture.xUnit2 3.46 和 xunit2 中的 Autofixture 3.46 AutoData 属性,在测试方法参数中实例化 Sum,我从断言中得到一个 Xunit.sdk.EqualException。

[Theory ]
[AutoData]
public void ShouldBeSum_AutoData(int a, int b, Sum uut )
{

    //problem
    int  residue = uut.Value; //not zero!
    //fix
    uut.Value = 0;

    //Arrange - in the parameter leads to problem
    // var uut =new Sum();

    //Act
    uut.Add(a);
    uut.Add(b);

    //Assert
    Assert.Equal(a + b, uut.Value);

}

似乎新 Sum 实例的 属性 值在实例化时未设置为类型的默认值(比如零)- 证明 'residue' 的非零值。

public class Sum
{
    public int Value { get; set; }

    public void Add(int number)
    {
        Value += number;
    }
}

从主体(和新的)实例化测试目标 uut 给出了预期的默认初始 属性 值。 因此 uut class 目前未完全从参数实例化 - 这是您的责任。

正在修复?

此行为是设计使然。 AutoFixture 旨在创建 并将数据 填充到对象中,因此这是它的默认行为。

您可以通过多种方式在 AutoFixture 中禁用 AutoProperties。在此特定示例中,最简单的修复方法是将 [NoAutoProperties] 属性应用于 uut 参数:

[Theory, AutoData]
public void ShouldBeSum_AutoData(int a, int b, [NoAutoProperties]Sum uut)
{
    uut.Add(a);
    uut.Add(b);

    Assert.Equal(a + b, uut.Value); // Passes
}

不过,还有其他更全面的方法可以达到同样的效果。


最后,这应该让我们停下来反思 Sum 的设计:Value 是一个可公开修改的 属性 是否合适? Sum class 的不变量不应该是 Value 保证 是使用 class 执行计算的结果(即通过调用 Add)?

这样的设计可能是这样的:

public class Summer
{
    public int Value { get; private set; }

    public void Add(int number)
    {
        Value += number;
    }
}

在这种情况下,以下测试自动通过:

[Theory, AutoData]
public void ShouldBeSum_AutoData(int a, int b, Summer uut)
{
    uut.Add(a);
    uut.Add(b);

    Assert.Equal(a + b, uut.Value); // Passes
}

AutoFixture 最初是作为测试驱动开发 (TDD) 的工具构建的,而 TDD 就是关于 反馈 的。本着 GOOS 的精神,您应该 听取您的测试 。如果测试很难写,你应该考虑你的 API 设计。 AutoFixture 倾向于放大这种反馈,因此对 AutoFixture 问题的一个好的反应是在查看 AutoFixture 本身之前查看 SUT。