C# 如何测试属性是否具有必需的注释?

C# 如何测试属性是否具有必需的注释?,c#,.net,C#,.net,我对属性的定义如下: [Required(ErrorMessage="The Year of Manufacture has to be filled")] public int? YearOfManufacture { get; set; } 如果属性设置了所需的注释,我如何编写单元测试,哪些测试?您可以有一个测试助手方法,该方法将在视图模型的特定实例上运行验证: public bool TryValidate(object model, out ICollection<Validat

我对属性的定义如下:

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

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

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

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
    );
}
public bool TryValidate(对象模型,out-ICollection结果)
{
var context=新的ValidationContext(模型,serviceProvider:null,items:null);
结果=新列表();
返回Validator.TryValidateObject(
模型、上下文、结果、验证所有属性: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);
}
[TestMethod]
需要制造年的公开作废()
{
//安排
var sut=新的MyViewModel();
sut.YearOfManufacture=null;
i收集结果;
//表演
var实际值=TryValidate(sut,out结果);
//断言
Assert.IsFalse(实际);
}

除了使用DataAnnotation之外,您还可以看看它,它允许您以流畅的方式表达更复杂的验证规则,它有一个很好的方法,您的验证规则更简单。

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

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
    );
}
public bool TryValidate(对象模型,out-ICollection结果)
{
var context=新的ValidationContext(模型,serviceProvider:null,items:null);
结果=新列表();
返回Validator.TryValidateObject(
模型、上下文、结果、验证所有属性: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);
}
[TestMethod]
需要制造年的公开作废()
{
//安排
var sut=新的MyViewModel();
sut.YearOfManufacture=null;
i收集结果;
//表演
var实际值=TryValidate(sut,out结果);
//断言
Assert.IsFalse(实际);
}

除了使用DataAnnotations,您还可以看看它能让您以流畅的方式表达更复杂的验证规则,它有一个很好的功能,您的验证规则更容易。

如果出于任何原因,您想测试一个属性是否被注释(而不是测试验证注释是否有效),您可以使用测试中建议的扩展方法:

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();
}
public static T GetAttributeFrom(此对象实例,string propertyName),其中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");
    }
}
类示例
{
[必需(ErrorMessage=“必须填写制造年份”)]
公共整数?制造年份{get;set;}
public int?notAttribute属性{get;set;}
}
静态类注释
{
公共静态T GetAttributeFrom(此对象实例,字符串propertyName),其中T:Attribute
{
var attrType=typeof(T);
var property=instance.GetType().GetProperty(propertyName);
return(T)property.GetCustomAttributes(attrType,false).FirstOrDefault();
}
}
班级计划
{
静态void Main(字符串[]参数)
{
var sampleInstance=新样本();
var annotation=sampleInstance.GetAttributeFrom(“制造年份”);
var nullAnnotation=sampleInstance.GetAttributeFrom(“notAttributeProperty”);
}
}

如果出于任何原因,您希望测试某个属性是否被注释(而不是测试验证注释是否有效),您可以使用测试中建议的扩展方法:

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();
}
public static T GetAttributeFrom(此对象实例,string propertyName),其中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");
    }
}
类示例
{
[必需(ErrorMessage=“必须填写制造年份”)]
公共整数?制造年份{get;set;}
public int?notAttribute属性{get;set;}
}
静态类注释
{
公共静态T GetAttributeFrom(此对象实例,字符串propertyName),其中T:Attribute
{
var attrType=typeof(T);
var property=instance.GetType().GetProperty(propertyName);
return(T)property.GetCustomAttributes(attrType,false).FirstOrDefault();
}
}
班级计划
{
静态void Main(字符串[]参数)
{
var sampleInstance=新样本();
var annotation=sampleInstance.GetAttributeFrom(“制造年份”);
var nullAnnotation=sampleInstance.GetAttributeFrom(“notAttributeProperty”);
}
}
我建议您这样做,这样您就可以非常干净地执行此操作:

typeof(MyType)
    .GetProperty("YearOfManufacture")
    .Should()
    .BeDecoratedWith<RequiredAttribute>("because MyType.YearOfManufacture is required.");
typeof(MyType)
.GetProperty(“制造年份”)
.Should()
.BeDecoratedWith(“因为需要MyType.YearOfManufacture.”);
我建议您这样做,这样您就可以非常干净地执行此操作:

typeof(MyType)
    .GetProperty("YearOfManufacture")
    .Should()
    .BeDecoratedWith<RequiredAttribute>("because MyType.YearOfManufacture is required.");
typeof(MyType)
.GetProperty(“制造年份”)
.Should()
.BeDecoratedWith(“因为需要MyType.YearOfManufacture.”);

如果没有它会发生什么?让它发生并检查它。这就是你要找的吗?为此编写单元测试有什么意义?是否接受这些答案中的任何一个?如果没有,会发生什么?让它发生并检查它。这就是你要找的吗?为此编写单元测试有什么意义?是否接受这些答案中的任何一个?您也可以通过调用
MyController.Validate(sut)
来使用控制器。您还可以通过调用