自动混合和自定义数据注释

时间:2014-08-05 20:26:42

标签: autofixture

我在我的设备和集成测试中使用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
}

它只是将提供的字符串限制为某个值(由于其他原因,我无法使用直接枚举)。

如何自定义自动混合以创建适当的数据?

2 个答案:

答案 0 :(得分:4)

目前,AutoFixture支持以下验证属性:

要支持自定义验证属性,您必须从以下其中一组进行推断:

然后,您必须将新创建的Relay和Generator类添加为Customizations

答案 1 :(得分:3)

想要提供更新以防其他人遇到同样的问题。我不想为我的解决方案中的每个自定义属性创建一个Relay,Request和Generator。相反,我创建了一个ISpecimenBuilder来处理一个地方的所有事情。

在我的情况下,我只对字符串有自定义属性。我创建的一些自定义属性是AlphaNumericAttributeEnumAttribute

这样的事情:

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

就是这样!