我在我的设备和集成测试中使用AutoFixture并遇到了问题。我生成数据传输对象,其中一些类在属性上具有DataAnnotation属性(其中一些是自定义的)。 AutoFixture会看到那些并且没有为它们生成数据,可能是因为它不确定它期待什么数据。
我使用的自定义验证属性示例:
public class Person
{
public string FullName { get; set; }
[Enum("M", "F")]
public string Gender { get; set; }
}
public class EnumAttribute : ValidationAttribute
{
public EnumAttribute(params string[] allowedStrings)
{
if (allowedStrings == null || allowedStrings.Length == 0)
throw new ArgumentException("allowedStrings");
AllowNull = true;
AllowedStrings = allowedStrings;
ErrorMessage = "The field '{0}' is invalid. Allowed strings are " + string.Join(", ", AllowedStrings);
}
// ... implementation
}
它只是将提供的字符串限制为某个值(由于其他原因,我无法使用直接枚举)。
如何自定义自动混合以创建适当的数据?
答案 0 :(得分:4)
目前,AutoFixture支持以下验证属性:
要支持自定义验证属性,您必须从以下其中一组进行推断:
然后,您必须将新创建的Relay和Generator类添加为Customizations
。
答案 1 :(得分:3)
想要提供更新以防其他人遇到同样的问题。我不想为我的解决方案中的每个自定义属性创建一个Relay,Request和Generator。相反,我创建了一个ISpecimenBuilder
来处理一个地方的所有事情。
在我的情况下,我只对字符串有自定义属性。我创建的一些自定义属性是AlphaNumericAttribute
和EnumAttribute
。
这样的事情:
public class CustomAnnotationsBuilder : ISpecimenBuilder
{
private readonly Random rnd = new Random();
public object Create(object request, ISpecimenContext context)
{
object result = new NoSpecimen(request);
var pi = request as PropertyInfo;
// do a few different inspections if it's a string
if (pi != null && pi.PropertyType == typeof(string))
{
// handle Enum attributes
if (Attribute.IsDefined(pi, typeof(EnumAttribute)))
{
var enumAttribute = (EnumAttribute)Attribute.GetCustomAttribute(
pi, typeof(EnumAttribute));
var allowedStrings = enumAttribute.GetAllowedStrings();
return allowedStrings[rnd.Next(0, allowedStrings.Length)];
}
if (Attribute.IsDefined(pi, typeof(StringLengthAttribute)))
{
var stringLengthAttribute = (StringLengthAttribute)Attribute.GetCustomAttribute(
pi, typeof(StringLengthAttribute));
minLength = stringLengthAttribute.MinimumLength;
maxLength = stringLengthAttribute.MaximumLength;
// do custom string generation here
return generatedString;
}
if (Attribute.IsDefined(pi, typeof(AlphaNumericAttribute)))
{
// do custom string generation here
return generatedString;
}
return result;
}
return result;
}
然后我可以将其添加到AutoFixture中,如下所示:
Fixture.Customizations.Add(new CustomAnnotationsBuilder());
Fixture.Customize(new NoDataAnnotationsCustomization()); // ignore data annotations since I'm handling them myself
就是这样!