Reputation: 427
I have property defined like this:
[Required(ErrorMessage="The Year of Manufacture has to be filled")]
public int? YearOfManufacture { get; set; }
How do I write Unit test, which tests, if the property has set the required Annotation?
Upvotes: 0
Views: 1903
Reputation: 978
If you - for what ever reason - want to test, that a property is annotated (instead of testing that a validation annotation works), you can use the extension method suggested here in your test:
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();
}
EDITED: (1) used FirstOrDefault() instead of First() to correctly handle non-annotated attributes. (2) @Pavel Straka: Added more sample code below to answer Pavel Straka's comment.
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");
}
}
Upvotes: 1
Reputation: 39329
I'd recommend FluentAssertions for this, which allows you to do this very cleanly:
typeof(MyType)
.GetProperty("YearOfManufacture")
.Should()
.BeDecoratedWith<RequiredAttribute>("because MyType.YearOfManufacture is required.");
Upvotes: 3
Reputation: 1039080
You could have a test helper method that will run the validation on a particular instance of your view model:
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
);
}
and then in your unit test:
[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);
}
Alternatively to using DataAnnotations you may take a look at FluentValidation.NET
which allows you to express much more complex validation rules in a fluent manner, it has a nice integration with MVC
and testing
your validation rules is even easier.
Upvotes: 2