AutoFixture,创建电子邮件地址列表

时间:2016-04-01 20:17:26

标签: c# unit-testing testing autofixture

我正在编写一些单元测试并且有一个名为Account的类

public Guid AccountId {get;set;}
public IEnumerable<string> EmailAddresses {get;set;}
etc...

我想使用autofixture创建帐户,但我无法获取电子邮件格式。

我试过了

fixture.Register<string>(() => string.Format("{0}@acme.com", fixture.Create<string>()));

但这会导致循环问题。

我能做到这一点

fixture.Register<string>(() => string.Format("{0}@acme.com", fixture.Create<int>()));

但我宁愿在地址的开头有一个字符串。

修改 感谢这两个答案,我在此处撰写了摘要和其他几个方案 - http://nodogmablog.bryanhogan.net/2016/04/customizing-a-specific-string-inside-a-class-using-autofixture/

2 个答案:

答案 0 :(得分:12)

有几种方法可以做到这一点。这是其中之一:

假设MyClass被定义为

public class MyClass
{
    public Guid AccountId { get; set; }
    public IEnumerable<string> EmailAddresses { get; set; }
}

然后,Fixture对象可以像这样自定义

var fixture = new Fixture();
fixture.Customize<MyClass>(c => c
    .With(x =>
        x.EmailAddresses,
        fixture.CreateMany<MailAddress>().Select(x => x.ToString())));

var result = fixture.Create<MyClass>();

因此EmailAddresses将填充如下所示的电子邮件字符串:

"18e743af-89ae-46b7-b38e-ff51425ec745@example.org"
"928bd85d-7d89-4cca-bff3-a12d5da6fe29@example.org"
"61db1178-8af9-489f-ba44-95c6393d84a9@example.com"

答案 1 :(得分:7)

这是AutoFixture为您提供关于对象模型可用性的反馈的情况之一。

如果EmailAddresses属性应该只包含有效的电子邮件地址,那么您应该问自己,将它们表示为通用字符串是the right choice。像MailAddress类这样的更具体的类型会限制该属性的有效值集。 它还可以更容易地为它生成测试数据,因为AutoFixture知道如何创建MailAddress的实例。

话虽如此,如果您无法更改对象模型,您仍然可以编写customization来告诉AutoFixture为IEnumerable<string>类型的任何属性或参数提供有效的电子邮件地址在他们名字的某个地方email

public class EmailAddressStringsGenerator : ISpecimenBuilder
{
    public object Create(object request, ISpecimenContext context)
    {
        if (IsEnumerableOfStringPropertyOrParameterNamedEmail(request))
        {
            return CreateManyEmailAddresses(context);
        }

        return new NoSpecimen();
    }

    static bool IsEnumerableOfStringPropertyOrParameterNamedEmail(object request)
    {
        return IsEnumerableOfStringPropertyNamedEmail(request) ||
               IsEnumerableOfStringParameterNamedEmail(request);
    }

    static bool IsEnumerableOfStringPropertyNamedEmail(object request)
    {
        var property = request as PropertyInfo;
        return property != null &&
               property.Name.ContainsIgnoringCase("email") &&
               typeof(IEnumerable<string>).IsAssignableFrom(property.PropertyType);
    }

    static bool IsEnumerableOfStringParameterNamedEmail(object request)
    {
        var parameter = request as ParameterInfo;
        return parameter != null &&
               parameter.Name.ContainsIgnoringCase("email") &&
               typeof(IEnumerable<string>).IsAssignableFrom(parameter.ParameterType);
    }

    static IEnumerable<string> CreateManyEmailAddresses(ISpecimenContext context)
    {
        var addresses = (IEnumerable<MailAddress>) 
            context.Resolve(typeof(IEnumerable<MailAddress>));
        return addresses.Select(a => a.Address);
    }
}

然后,您可以在Fixture中使用该自定义,方法是将其添加到Customizations属性中:

fixture.Customizations.Insert(0, new EmailAddressStringsGenerator());