Test Driving Model Validation in ASP.NET MVC3 - Part 2
In Part-1of this small blog post series, we have explored a way to do the TDD of controller’s responsibility in the context of model validation. In this Part-2 we are going to see “How to do the TDD of Model Validation”
Before getting into the business let us have a quick look at how ASP.NET MVC3 does the model validation. Internally when making an Http POST/GET request, MVC3 makes use of a helper class Validator located in the namespace System.ComponentModel.DataAnnotations. Validator can be used to validate the models based on the ValidationAttribute attributes associate with the model. After validating MVC3 adds the validation results to the controller’s ModelState Property by the AddModelError method which in turn sets the ModelState.IsValid property (Refer Part-1). We are actually going to make use of this Validator helper class going to test drive the model validation.
Let us start with a small requirement
“Employee name should not be empty”
The corresponding unit test will be like as follows
ValidateObject Method determines whether the specified object is valid using the validation context and throws a ValidationException if the object is invalid.
Employee Model will be like as follows
When you run the test “EmployeeNameShouldNotBeEmpty”, it will Fail with the error message “System.ComponentModel.DataAnnotations.ValidationException was expected”. Now it’s time to make it Pass. Thanks to RequiredAttribute we can make the test the pass without much effort. Just decorate the Name property with the [Required] Attribute. That’s it. Now run the test and it will Pass. As there is no scope for Refactoring, we will be ignoring it.
Well, we have done the TDD of model validation. Now let’s move onto the next requirement.
“Employee age should be greater than 30”
Let’s write the unit test for this requirement.
When we run the test, we’d get a failing test with error message “System.ComponentModel.DataAnnotations.ValidationException was expected”
Like RequiredAttribute we don’t have any AgeLimit Attribute to make the test pass. However we can create such kind of CustomAttributes. Another approach would be making use of IValiadatableObject
I will be using the latter option in this blog post, if you are interested in creating custom attribute refer this blog post
Here we go; the modified Employee model will look like as follows
The Validator helper class will invoke the Validate method of the model if the model passed to the ValidateObject Method implements the IValidatableObject.
Hurrah! Now you will be getting a passing test. We have done the TDD of Model Validation.
The bottom-line is we should not combine the unit tests of model validation with the controller’s unit tests and both should be kept separate. You can download the source code which we’ve seen in this blog post series from here