将DRY应用于自动固定“构建"程序.陈述 [英] Applying DRY to Autofixture "Build" statements

查看:38
本文介绍了将DRY应用于自动固定“构建"程序.陈述的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Assume I have this concrete class:

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

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

And I want to create an anonymous instance that has a valid email address, and the fullname field is no more than 20 characters. I can do this:

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类:

Is there a way that I can define this in one place, so that AF knows that I can get my customized anon class by using:

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

推荐答案

您有多种选择.我认为,最好的选择是采用 GOOS 监听测试原则.当测试变得难以编写时,该重新考虑被测系统(SUT)的设计了.AutoFixture倾向于放大这种效果.

You have various options. In my opinion, the best option is to apply the GOOS principle of listening to your tests. When the test becomes difficult to write, it's time to reconsider the design of the System Under Test (SUT). AutoFixture tends to amplify this effect.

重构为价值对象

如果您要求 Email FullName 属性应具有特别受约束的值,则它可能表示代替规范的自动修复示例与电话号码有关.

If you have a requirement that the Email and FullName properties should have particularly constrained values, it might indicate that instead of Primitive Obsession, the target API would benefit from defining explicit Email and FullName Value Objects. The canonical AutoFixture example is about phone numbers.

使用数据注释

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

You can also use data annotations to give AutoFixture hints about the constraints of the values. Not all data annotation attributes are supported, but you can use both MaxLength and RegularExpression.

它可能看起来像这样:

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; }
}

我个人不喜欢这种方法,因为我更喜欢正确的封装.

Personally, I don't like this approach, because I prefer proper encapsulation instead.

使用自定义

代替使用 Build< T> 方法,而使用 Customize< T> 方法:

Instead of using the Build<T> method, use the Customize<T> method:

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>();

编写一个由惯例驱动的标本生成器

最后,您可以编写会议驱动的自定义:

public class EmailSpecimenBuilder : ISpecimenBuilder
{
    public object Create(object request,
        ISpecimenContext context)
    {
        var pi = request as PropertyInfo;
        if (pi == null)
        {
            return new NoSpecimen(request);
        }

        if (pi.PropertyType != typeof(string)
            || pi.Name != "Email")
        {
            return new NoSpecimen(request);
        }

        return string.Format("{0}@fobar.com", context.Resolve(typeof(string)));
    }
}

我真的很喜欢这种方法,因为我可以在这里放置任意复杂的逻辑,因此不必创建大量的一次性定制,我可以使用一小套约定来驱动整个测试套件.这也会使目标代码更加一致.

This approach I really like, because I can put arbitrarily complex logic here, so instead of having to create a lot of one-off customizations, I can have a small set of conventions driving an entire test suite. This also tends to make the target code more consistent.

这篇关于将DRY应用于自动固定“构建"程序.陈述的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆