Let’s take one basic model
public class Person : ModelBase
{
[Required(ErrorMessage)=typeof(ErrorStrings), ErrorMessageResourceName="Required")]
public string FirstName{get;set;}
}
To be able to test Required attribute, at some point I will need to
- instantiate the person class
- assign an invalid value to the FirstName property whic would be
null
orString.Empty
- have some validation logic in this class or in one of its base classes (in this case ModelBase or Object)
While looking for a good way to do that , I have find a nice helper method shared by scorpio in this stackoverflow post. If we elaborate the 3rd point above, 3 options came to my mind
- embed the validation logic to ModelBase class, hence all the model will take benefit of it
- create an extension method for ModelBase class
- create an extension method for Object class
I eliminated 3rd option since only my entity model classes would need the validation logic. In addition
to that in my opinion, it is not a good practice to create directly this kind of “limited scoped”
behaviors on Object
class. Let’s recall, everything in .Net inherits from Object class. So I
opted for the 2nd option but I might as well as go for the 1st. Here is the result :
internal static void Validate(this ModelBase model)
{
var type = model.GetType();
var meta = type.GetCustomAttributes(false).OfType<MetadataTypeAttribute>().FirstOrDefault();
if (meta != null)
{
type = meta.MetadataClassType;
}
var propertyInfo = type.GetProperties();
foreach (var info in propertyInfo)
{
var attributes = info.GetCustomAttributes(false).OfType<ValidationAttribute>();
foreach (var attribute in attributes)
{
var objPropInfo = obj.GetType().GetProperty(info.Name);
attribute.Validate(objPropInfo.GetValue(obj, null), info.Name);
}
}
}
It’s important to note that attribute.Validate(...)
statement will throw an exception in case one
of the property values is not confirm with the wanted validation behaviour in our case Required Ready
to roll, let’s write the test. The goal will be make a statement using Validate() method, make it throw
an exception and test that.
[Test]
public void FirstNameIsRequired()
{
var person = new Person{FirstName = String.Empty};
Assert.That(()=>person.IsValid(),
Throws.
Exception.
TypeOf<ValidationException>());
}