将DRY应用于自动混合“构建”语句

时间:2014-03-11 17:11:33

标签: c# autofixture

假设我有这个具体的课程:

public partial class User
{
    public int ID { get; set; }
    public string Email { get; set; }
    public string FullName { get; set; }
}

我想创建一个具有有效电子邮件地址的匿名实例,而fullname字段不超过20个字符。我可以这样做:

var fixture = new Fixture();
var anonUser = fixture.Build<User>()
    .With(x => x.Email, string.Format("{0}@fobar.com", fixture.Create<string>()))
    .With(x => x.FullName,  fixture.Create<string>()Substring(0,20))
    .Create();

有没有办法可以在一个地方定义这个,所以AF知道我可以通过使用以下方式获得我自定义的anon类:

var newAnon = fixture.Build<User>();

1 个答案:

答案 0 :(得分:12)

你有各种选择。在我看来,最好的选择是应用听取您的测试的GOOS原则。当测试变得难以编写时,是时候重新考虑被测系统(SUT)的设计了。 AutoFixture倾向于放大这种效果。

重构为价值对象

如果您要求EmailFullName属性具有特别受约束的值,则可能表明目标API将受益于定义显式Primitive Obsession而不是canonical AutoFixture example is about phone numbers。 1}}和Email 值对象data annotations

使用数据注释

您还可以使用MaxLength提供有关值约束的AutoFixture提示。并非所有数据注释属性都受支持,但您可以同时使用RegularExpressionproper encapsulation

它可能看起来像这样:

FullName

就个人而言,我不喜欢这种方法,因为我更喜欢convention-driven customization

使用自定义

不使用public partial class User { public int ID { get; set; } [RegularExpression("regex for emails is much harder than you think")] public string Email { get; set; } [MaxLenght(20)] public string FullName { get; set; } } 方法,而是使用Build<T>方法:

Customize<T>

编写会议驱动的标本生成器

最后,您可以撰写{{3}}:

var fixture = new Fixture();
fixture.Customize<User>(c => c
    .With(x => x.Email, string.Format("{0}@fobar.com", fixture.Create<string>())
    .With(x => x.FullName, fixture.Create<string>().Substring(0,20)));
var newAnon = fixture.Create<User>();

我非常喜欢这种方法,因为我可以在这里放置任意复杂的逻辑,因此我不需要创建大量的一次性自定义,而是可以通过一小组约定来驱动整个测试套件。这也有助于使目标代码更加一致。