如何配置AutoFixture以在创建许多特定类型时使用枚举值作为种子?

Dan*_*rth 6 .net c# autofixture

我有以下类型:

public enum Status
{
    Online,
    Offline
}

public class User
{
    private readonly Status _status;
    public User(Status status) { _status = status; }
    public Status Status {get {return _status; }}
    public string Name {get;set;}
}
Run Code Online (Sandbox Code Playgroud)

现在,在执行时fixture.CreateMany<User>我希望AutoFixture返回两个Users,每个状态一个.所有其他属性 - 如Name- 应该填充匿名数据.

问题:
如何配置AutoFixture来执行此操作?


我尝试了以下这个:

  1. 注册User对象的新闻集合:

    fixture.Register(
        () => Enum.GetValues(typeof(Status)).Cast<Status>().Select(s => 
            new User(s)));
    
    Run Code Online (Sandbox Code Playgroud)

    这种方法的问题是AutoFixture不会填充其他属性 Name

  2. 自定义User使用工厂并注册使用fixture.Create以下内容的集合:

        f.Customize<User>(c => c.FromFactory((Status s) => new User(s)));
        f.Register(() =>
            Enum.GetValues(typeof(Status))
                .Cast<Status>()
                .Select(s => (User)f.Create(new SeededRequest(typeof(User), s),
                                            new SpecimenContext(f))));
    
    Run Code Online (Sandbox Code Playgroud)

    那也行不通.种子没有被使用.

Nik*_*nis 5

您可以声明并使用自定义,例如StatusGenerator

var fixture = new Fixture();
fixture.RepeatCount = 2;
fixture.Customizations.Add(new StatusGenerator());

var result = fixture.CreateMany<User>();
Run Code Online (Sandbox Code Playgroud)

假设实现StatusGenerator可能如下:

internal class StatusGenerator : ISpecimenBuilder
{
    private readonly Status[] values;
    private int i;

    internal StatusGenerator()
    {
        this.values =
            Enum.GetValues(typeof(Status)).Cast<Status>().ToArray();
    }

    public object Create(object request, ISpecimenContext context)
    {
        var pi = request as ParameterInfo;
        if (pi == null || !pi.ParameterType.IsEnum)
            return new NoSpecimen(request);

        return this.values[i == this.values.Length - 1 ? i = 0 : ++i];
    }
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*ann 5

你可以这样做:

var users = new Fixture().Create<Generator<User>>();

var onlineUser = users.Where(u => u.Status == Status.Online).First();
var offlineUser = users.Where(u => u.Status == Status.Offline).First();
Run Code Online (Sandbox Code Playgroud)

如果您使用的是AutoFixture.Xunit,则声明性等效项为:

[Theory, AutoData]
public void CreateOneOfEachDeclaratively(Generator<User> users)
{
    var onlineUser = users.Where(u => u.Status == Status.Online).First();
    var offlineUser = users.Where(u => u.Status == Status.Offline).First();

    // Use onlineUser and offlineUser here...
}
Run Code Online (Sandbox Code Playgroud)

  • 好的,如果我使属性可写,我可以重现这个,并且*保持*构造函数参数.你在这里看到的是共振效应,因为每个实例都接收*完全*两个"状态"实例,并且因为只有两个"状态"值,它总是最终是相同的,因为枚举值是(仍然以确定的循环方式生成.也许我们应该更改AutoFixture的默认行为,但这将是一个重大变化...如果你可以使属性为只读,删除构造函数参数,或使用更大的枚举,你应该是好的. (2认同)