AutoFixture,创建电子邮件地址列表
AutoFixture, create a list of email addresses
我正在编写一些单元测试并有一个名为 Account
的 class,其中有
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>()));
但我宁愿在地址开头有一个字符串。
编辑
感谢这两个答案,我在这里写了一个摘要和一些其他场景作为 post - http://nodogmablog.bryanhogan.net/2016/04/customizing-a-specific-string-inside-a-class-using-autofixture/
有几种方法可以做到这一点。这是其中之一:
假设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.Address)));
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"
这是 AutoFixture 向您提供有关对象模型可用性的反馈的情况之一。
如果 EmailAddresses
属性 应该只包含有效的电子邮件地址,那么您应该问问自己是否将它们表示为通用字符串 the right choice. A more specific type like the MailAddress
class 会限制属性 的一组有效值。
它还可以更容易地为它生成测试数据,因为 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());
来自自动夹具
var localPart = fixture.Create<EmailAddressLocalPart>().LocalPart;
var domain = fixture.Create<DomainPart>().Domain;
var fullAddress = $"{localPart}@{domain}";
我正在编写一些单元测试并有一个名为 Account
的 class,其中有
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>()));
但我宁愿在地址开头有一个字符串。
编辑 感谢这两个答案,我在这里写了一个摘要和一些其他场景作为 post - http://nodogmablog.bryanhogan.net/2016/04/customizing-a-specific-string-inside-a-class-using-autofixture/
有几种方法可以做到这一点。这是其中之一:
假设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.Address)));
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"
这是 AutoFixture 向您提供有关对象模型可用性的反馈的情况之一。
如果 EmailAddresses
属性 应该只包含有效的电子邮件地址,那么您应该问问自己是否将它们表示为通用字符串 the right choice. A more specific type like the MailAddress
class 会限制属性 的一组有效值。
它还可以更容易地为它生成测试数据,因为 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());
来自自动夹具
var localPart = fixture.Create<EmailAddressLocalPart>().LocalPart;
var domain = fixture.Create<DomainPart>().Domain;
var fullAddress = $"{localPart}@{domain}";