C# 如何配置AutoFixture,以便在创建许多特定类型时使用枚举值作为种子?
我有以下几种:C# 如何配置AutoFixture,以便在创建许多特定类型时使用枚举值作为种子?,c#,.net,autofixture,C#,.net,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;}
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时,我希望AutoFixture返回两个用户,每个状态一个。所有其他属性(如Name
)都应使用匿名数据填充
问题:
如何配置AutoFixture来执行此操作
为此,我尝试了以下方法:
注册更新用户
对象的集合:
fixture.Register(
() => Enum.GetValues(typeof(Status)).Cast<Status>().Select(s =>
new User(s)));
那也没用。种子没有被使用
您可以声明并使用自定义项,例如,StatusGenerator
:
var fixture = new Fixture();
fixture.RepeatCount = 2;
fixture.Customizations.Add(new StatusGenerator());
var result = fixture.CreateMany<User>();
您可以这样做:
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();
var users=newfixture().Create();
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...
}
[理论,自动数据]
public void createOneOfechDeclarative(生成器用户)
{
var onlineUser=users.Where(u=>u.Status==Status.Online).First();
var offlineUser=users.Where(u=>u.Status==Status.Offline).First();
//在此处使用联机用户和脱机用户。。。
}
基于此,我现在使用的是:
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
fixture.Customize(c=>c.Without(x=>x.Status));
夹具。定制(
c=>
c、 从工厂(
()=>Enum.GetValues(typeof(Status)).Cast()
。选择(s=>users.First(u=>u.Status==s));
fixture.Create();//返回两个用户
我知道已经有答案了,发电机是一个非常有趣的发现。
我认为有一个更简单的方法来解决这个问题
var numberOfEnumValues = Enum.GetValues(typeof(Status)).Length;
var users = fixture.CreateMany<User>(numberOfEnumValues);
那么这将永远不会被评估:
var users = fixture.Create<Generator<SuperUser>>();
var offlineUser = users.Where(u => u.Status == Status.Offline).First();
var users=fixture.Create();
var offlineUser=users.Where(u=>u.Status==Status.Offline).First();
很好,谢谢。是否可以不设置重复计数?据我所知,这会影响对CreateMany
的所有调用,而不仅仅是对User
的调用……谢谢您的回答。不幸的是,如果Status
属性不是readonly
,则这不起作用First
“never”返回(我至少等待了30秒)。readonly
关键字与此无关。我刚刚从我的复制中删除了readonly
关键字,但它并没有改变结果。我不是说backing字段不是只读的。我所说的属性不是只读的,即公共状态状态{get;set;}
。好的,如果我使属性可写,并保留构造函数参数,我可以复制这个属性。您在这里看到的是一种共振效应,因为每个实例恰好接收到两个状态的实例,并且因为只有两个状态的值,所以它最终总是相同的,因为枚举值(仍然)是以确定的循环方式生成的。也许我们应该更改AutoFixture的默认行为,但这将是一个突破性的更改。。。如果您可以将属性设置为只读、删除构造函数参数或使用更大的枚举,您应该会做得很好。感谢您的解释-这很有意义。另一种“修复”它的方法是使用c=>c.Without(x=>x.Status)
定制User
。在我看来,这是最干净的解决方案,因为它不涉及用户
类本身,而类本身(希望)有充分的理由按照它的方式设计。(请注意:User
只是这个问题的一个例子。没有必要讨论这个特定的设计是否好)。
var numberOfEnumValues = Enum.GetValues(typeof(Status)).Length;
var users = fixture.CreateMany<User>(numberOfEnumValues);
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();