你如何对数据注解进行单元测试?

6
两个类属性具有以下注释:
    [Key]
    [Column]
    [Required]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }


    [MaxLength(25)]
    public string Name { get; set; }

我知道测试Key,Column和Required属性已经不再是单元测试,因为它会依赖底层数据库,但是如何测试MaxLength(25)属性呢?
我能想到的其中一个替代方案是将代码约束添加到属性中。
更新:
如建议所示,我编写了以下帮助程序:
    public class AttributeHelper <T> where T : class
    {
        private Type GivenClass 
        { 
            get { return typeof (T); }
        }

        public bool HasAnnotation(Type annotation)
        {
            return GivenClass.GetCustomAttributes(annotation, true).Single() != null;
        }

        public bool MethodHasAttribute(Type attribute, string target)
        {
           return GivenClass.GetMethod(target).GetCustomAttributes(attribute, true).Count() == 1;
        }

        public bool PropertyHasAttribute(Type attribute, string target)
        {
            return GivenClass.GetProperty(target).GetCustomAttributes(attribute, true).Count() == 1;
        }

    }

我已经测试了我的助手:
    [TestMethod]
    public void ThisMethod_Has_TestMethod_Attribute()
    {
        // Arrange
        var helper = new AttributeHelper<AttributeHelperTests>();

        // Act
        var result = helper.MethodHasAttribute(typeof (TestMethodAttribute), "ThisMethod_Has_TestMethod_Attribute");

        // Assert
        Assert.IsTrue(result);
    }

除了使用反射时方法和属性必须是公共的以外,一切都正常。我无法想象任何需要在私有属性/方法中添加属性的情况。

然后测试EF注释:

        public void IdProperty_Has_KeyAttribute()
        {
            // Arrange
            var helper = new AttributeHelper<Player>();

            // Act
            var result = helper.PropertyHasAttribute(typeof (KeyAttribute), "Id");

            // Assert
            Assert.IsTrue(result);
        }

2
我认为,通过测试属性是否发挥作用而不是测试基础业务逻辑,您正在测试属性框架,这不是您应该测试的内容(Microsoft已经完成了这项工作)。您想要的只是在业务层中确保如果传递一个长度为26个字符的字符串,该方法返回某种违规原因,因为25是最大长度。您可以编写一个单元测试来针对业务层传递一个26个字符的字符串。如果您想测试您的UI层不允许输入超过25个字符,请使用Selenium或类似工具。 - Nope
1个回答

9
我知道测试Key,Column和Required属性不再是单元测试,因为它依赖于底层数据库,所以现在是集成测试。但是,你可以轻松地测试Id属性是否标记了所有这些属性,并且它属于单元测试类别。
[Test]
public void Id_IsMarkedWithKeyAttribute()
{
    var propertyInfo = typeof(MyClass).GetProperty("Id");

    var attribute = propertyInfo.GetCustomAttributes(typeof(KeyAttribute), true)
        .Cast<KeyAttribute>()
        .FirstOrDefault();

    Assert.That(attribute, Is.Not.Null);
}

这样,您可以确保您的属性被标记上您能想到的任何属性。当然,这需要一些反射工作,但这就是您测试属性标记的方法。


这非常有帮助,我从这个角度还没有考虑过。我以为我必须通过与数据库交互并检查是否已执行约束和检查来验证属性是否有效。这就是为什么我说它是一个集成测试的原因。 - user338195
1
@CodeWorks:当然,集成测试也会验证这些属性的存在。但是有一个主要缺点-你不像单元测试那样经常运行集成测试。此外,它们需要更长的时间来运行。由于使用这些属性标记您的属性是一种合同,因此应像任何其他合同一样进行单元测试。长话短说-最好的方法是拥有两组测试。 - k.m
刚刚为建议的辅助程序编写了一些单元测试。反射仅适用于公共属性。 - user338195

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接