我有以下类型:
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;}
}
现在,执行fixture.CreateMany<User>
时,我希望AutoFixture返回两个Users
,每个状态一个。所有其他属性 - 如Name
- 应填充匿名数据。
问题:
如何配置AutoFixture来执行此操作?
我尝试了以下这个:
注册新闻User
对象的集合:
fixture.Register(
() => Enum.GetValues(typeof(Status)).Cast<Status>().Select(s =>
new User(s)));
此方法的问题是AutoFixture不会填充其他属性,例如Name
自定义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))));
这也不起作用。种子没有被使用。
答案 0 :(得分: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();
如果您使用的是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...
}
答案 1 :(得分:4)
基于Mark's answer,这就是我现在使用的:
fixture.Customize<User>(c => c.Without(x => x.Status));
fixture.Customize<IEnumerable<User>>(
c =>
c.FromFactory(
() => Enum.GetValues(typeof(Status)).Cast<Status>()
.Select(s => users.First(u => u.Status == s))));
fixture.Create<IEnumerable<User>>(); // returns two Users
答案 2 :(得分:3)
您可以声明并使用自定义,例如StatusGenerator
:
var fixture = new Fixture();
fixture.RepeatCount = 2;
fixture.Customizations.Add(new StatusGenerator());
var result = fixture.CreateMany<User>();
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];
}
}
答案 3 :(得分:2)
我知道它已经回答了,发电机是一个非常有趣的发现。 我认为这个问题有一个更简单的方法。
var numberOfEnumValues = Enum.GetValues(typeof(Status)).Length;
var users = fixture.CreateMany<User>(numberOfEnumValues);
如果构造函数更复杂,具有多个Status值,或者模型具有Status类型的属性设置器。那么你通常会遇到问题,发电机也可能会爆炸。
说:
public class SuperUser : User
{
public SuperUser(Status status, Status shownStatus): base(status)
{
}
}
然后永远不会评估这个:
var users = fixture.Create<Generator<SuperUser>>();
var offlineUser = users.Where(u => u.Status == Status.Offline).First();