如何通过AutoFixture创建TestClass时修复某些属性的范围

sow*_*wen 7 unit-testing autofixture

有谁知道我怎么能告诉AutoFixture在做某些属性时指定一个范围(最小和最大)

MyDataClass obj = fixture.Create<MyDataClass>();
Run Code Online (Sandbox Code Playgroud)

其中MyDataClass具有属性Diameter,我只希望min:1和max:60在这个属性上.

Mar*_*ann 13

数据注释

最简单的方法可能是装饰的性质本身就带有数据注释,虽然我已经不是我自己的这一个巨大的风扇:

public class MyDataClass
{
    [Range(1, 60)]
    public decimal Diameter { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

AutoFixture将尊重[Range]属性的值.

公约为基础

在我看来,更好的方法是基于约定的方法,它不依赖于不可执行的属性:

public class DiameterBuilder : ISpecimenBuilder
{
    public object Create(object request, ISpecimenContext context)
    {
        var pi = request as PropertyInfo;
        if (pi == null ||
            pi.Name != "Diameter" ||
            pi.PropertyType != typeof(decimal))
            return new NoSpecimen(request);

        return context.Resolve(
            new RangedNumberRequest(typeof(decimal), 1.0m, 60.0m));
    }
}
Run Code Online (Sandbox Code Playgroud)

此通过测试演示了如何使用它:

[Fact]
public void ResolveRangeLimitedType()
{
    var fixture = new Fixture();
    fixture.Customizations.Add(new DiameterBuilder());
    var actual = fixture.Create<Generator<MyDataClass>>().Take(100);
    Assert.True(actual.All(x => 1 <= x.Diameter && x.Diameter <= 60));
}
Run Code Online (Sandbox Code Playgroud)

有关详细信息,请参阅此另一篇非常密切相关的SO Q&A.

克服原始的痴迷

也许更好的方法是听取你的测试,打击原始痴迷,并引入一个自定义类型 - 在这种情况下,一个Diameter值对象.

这通常是我的首选方法.