【问题标题】:AutoFixture and Custom DataAnnotationsAutoFixture 和自定义数据注释
【发布时间】:2014-08-05 20:26:41
【问题描述】:

我在单元和集成测试中使用 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
}

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

如何自定义 AutoFixture 以创建适当的数据?

【问题讨论】:

    标签: autofixture


    【解决方案1】:

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

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

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

    【讨论】:

    • 谢谢!这让我很好地了解了我需要做什么。但希望有更简单的方法,我需要制作 5 个自定义属性,即 15 个类,不计算自定义。
    【解决方案2】:

    我不想为解决方案中的每个自定义属性创建中继、请求和生成器。相反,我创建了一个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
    

    就是这样!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-03
      相关资源
      最近更新 更多