【问题标题】:How do I test if a property has required annotation?如何测试属性是否需要注释?
【发布时间】:2015-04-12 04:07:59
【问题描述】:

我有这样定义的属性:

[Required(ErrorMessage="The Year of Manufacture has to be filled")]
public int? YearOfManufacture { get; set; }

如果属性设置了所需的Annotation,我该如何编写单元测试,测试哪些?

【问题讨论】:

标签: c# .net


【解决方案1】:

您可以有一个测试助手方法,该方法将在您的视图模型的特定实例上运行验证:

public bool TryValidate(object model, out ICollection<ValidationResult> results)
{
    var context = new ValidationContext(model, serviceProvider: null, items: null);
    results = new List<ValidationResult>();
    return Validator.TryValidateObject(
        model, context, results, validateAllProperties: true
    );
}

然后在你的单元测试中:

[TestMethod]
public void YearOfManufacture_Is_Required()
{
    // arrange
    var sut = new MyViewModel();
    sut.YearOfManufacture = null;
    ICollection<ValidationResult> results;

    // act
    var actual = TryValidate(sut, out results);

    // assert
    Assert.IsFalse(actual);
}

除了使用DataAnnotations,您还可以查看FluentValidation.NET,它允许您以流畅的方式表达更复杂的验证规则,它有一个很好的integration with MVCtesting,您的验证规则更加容易。

【讨论】:

【解决方案2】:

我会为此推荐FluentAssertions,它可以让你非常干净地做到这一点:

typeof(MyType)
    .GetProperty("YearOfManufacture")
    .Should()
    .BeDecoratedWith<RequiredAttribute>("because MyType.YearOfManufacture is required.");

【讨论】:

  • 我根本不喜欢这个测试:属性名称被弱类型化为字符串,它测试显式实现(属性修饰)。如果验证是通过不同的系统完成的,比如流利的验证规则呢?功能没有变化,但所有测试都失败了。
  • 公平点,绝对值得一提。一个可能调用 YAGNI 以防止它在未来切换验证框架,但这取决于更大的上下文。我对所提出的问题进行了简洁的回答。
【解决方案3】:

如果您 - 无论出于何种原因 - 想要测试,属性被注释(而不是测试验证注释是否有效),您可以使用建议的扩展方法 here 在您的测试:

public static T GetAttributeFrom<T>(this object instance, string propertyName) where T : Attribute
{
    var attrType = typeof(T);
    var property = instance.GetType().GetProperty(propertyName);
    return (T)property .GetCustomAttributes(attrType, false).FirstOrDefault();
}

编辑: (1) 使用 FirstOrDefault() 而不是 First() 来正确处理非注释属性。 (2) @Pavel Straka:在下面添加了更多示例代码来回答 Pavel Straka 的评论。

class Sample
{
    [Required(ErrorMessage = "The Year of Manufacture has to be filled")]
    public int? YearOfManufacture { get; set; }

    public int? NotAttributedProperty { get; set; }
}

static class Annotations
{
    public static T GetAttributeFrom<T>(this object instance, string propertyName) where T : Attribute
    {
        var attrType = typeof(T);
        var property = instance.GetType().GetProperty(propertyName);
        return (T)property.GetCustomAttributes(attrType, false).FirstOrDefault();
    }
}

class Program
{
    static void Main(string[] args)
    {
        var sampleInstance = new Sample();
        var annotation = sampleInstance.GetAttributeFrom<RequiredAttribute>("YearOfManufacture");
        var nullAnnotation = sampleInstance.GetAttributeFrom<RequiredAttribute>("NotAttributedProperty");
    }
}

【讨论】:

  • 我得到错误:System.Array 不包含 First 的定义并且没有扩展方法 First 可以找到接受 System.Array 类型的第一个参数(您是否缺少 using 指令或程序集引用) ?我无法添加对 System.Array 的引用。我怎么能解决这个问题?谢谢
  • @PavelStraka:查看我的编辑答案。
猜你喜欢
  • 1970-01-01
  • 2016-12-17
  • 2020-03-09
  • 2023-03-08
  • 2019-02-16
  • 1970-01-01
  • 1970-01-01
  • 2022-06-14
  • 2015-09-20
相关资源
最近更新 更多