使用受限随机值自定义AutoFixture属性生成

4

背景

我想创建一个类的集合,但其中一些字符串属性具有受限制的值。我希望这些值在受限制的集合内随机生成。

我找到了自定义的方法,但是我的随机生成实现似乎没有使用任何AutoFixture特性,我不想重复造轮子:

var random = new Random();
var fixture = new Fixture();
fixture.Customize<MyClass>(b => b
    .With(i => i.MyProperty, random.Next(2) == 0 ? "O" : "C"));

var result = fixture.CreateMany<MyClass>(1000);

问题

有没有更有效率的方法告诉AutoFixture我想要一个随机字符串 "O" 或 "C"?

编辑

与此同时,我意识到上面的代码根本不起作用,所以它不适合作为“备份”计划。(表达式:random.Next(2) == 0 ? "O" : "C" 只会计算一次)


请参阅https://dev59.com/dJPfa4cB1Zd3GeqPItg_。 - Mark Seemann
@MarkSeemann:也许是我自己的问题,但我无法弄清楚如何链接答案。两个链接都是定制特定对象“MyClass”或StreetName生成。在我的情况下,对象是“string”。顺便说一句,我意识到我的示例无法工作,因为表达式“random.Next(2) == 0 ? "O" : "C"”只被评估一次(我明白为什么,这不是问题的一部分)。我也理解领域建模会更好,但当我的任务是编写单元测试时,我不能根据自己对代码编写方式的想法重写企业应用程序。 - g.pickardou
好的,我已经重新打开了这篇帖子,所以我会在这里留下链接,让其他人可以看到我链接的内容:https://dev59.com/vafja4cB1Zd3GeqPv3Ax - Mark Seemann
解决这个问题最简单的方法可能是引入一个特定于测试的辅助类型,您可以使用ElementsBuilder进行配置,然后添加一个ISpecimenBuilder,将某些字符串的请求转发到该辅助类型。请参阅上面的链接以及以下链接获取一些示例:https://stackoverflow.com/a/49492820/126014 - Mark Seemann
好的,所有三个都读完了。虽然都很清楚,但对于一个简单的日常任务来说,它们都太过繁琐了。我的意思是,在数据模型中可能会有数以亿计的简单类型属性(字符串、整数),我们必须从有限的集合中进行选择。对于所有这些属性,我们必须反复引入辅助对象,并编写数十行代码...主要是通过复制和粘贴(或开发辅助基础设施以防止复制和粘贴)来实现,这听起来并不实用,也不会提高生产力... - g.pickardou
1个回答

7

自从AutoFixture 4.6.0以来,您可以在With定制函数内部使用回调函数。这允许限制字段值,但仍然使其在创建的样本之间变化。

源代码示例:

[Fact]
public void CustomizeMany()
{
    var fixture = new Fixture();
    var items = fixture.Build<MyClass>()
        .With(x => x.EvenNumber, (int number) => number * 2)
        .CreateMany(1000)
        .ToArray();

    Assert.All(items, item => Assert.Equal(0, item.EvenNumber % 2));
}

public class MyClass
{
    public int EvenNumber { get; set; }
}

您可以调整示例以满足您的特定需求。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接