Test Driving Model Validation in ASP.NET MVC3 - Part 1

Entity Framework 4.1(EF4.1) provides in-built support for defining the validation constraints in model through Data Annotation attributes and Fluent API. It’s one of the cool features provided by EF4.1 that enables the developers to define validation rules of the model in an easy and more maintainable way. In addition to that MVC3 framework makes use of these validation model and supports both client and server side validation without writing any code!

I’m in the early days of practicing Test Driven Development (TDD). Fortunately I have got an opportunity to implement TDD in my current assignment. I feel I am much oriented and focused towards the solution while using TDD. Also it makes me to critique my design and the way I do the coding. I would like to be a better programmer and looking forward to improve myself and hence TDD suits me more. Learning TDD and practicing it is totally different! Yes, in theory it is very easy to read and understand TDD. But when you practice it, you will encounter many more interesting things about TDD and in fact it’s where you can actually learn TDD.

Okay, how to do TDD with Controller’s responsibility in the context of Model validation in MVC3. Well, it is easy but we should understand and find out what exactly we want to test and the way to test them. Many articles and blog posts suggest doing it through the controller. Is it really a good approach to test the model validation through controller?   Kindly think of it for a moment. I feel it is not a right way to deal this stuff. 

Let me explain it through a small example. Consider an Employee model which has two properties Name and Age and an EmployeeController responsible for doing CRUD on Employee Model. What is the responsibility of EmployeeController when creating a new Employee data? It should check whether the posted employee model is valid or not, if it is valid add to the database else return the view with the validation errors. MVC3 framework makes life easy by automatically validating the Posted model and set the IsValid Property of the ModelState and also add validation errors to the model. Hence controller’s job is very easy as follows



Corresponding TestCases

  • When creating a new employee, if the passed employee data is valid, it should be added to the database
  • When creating a new employee, if the passed employee data is InValid, it should not add to the database and show the view with validation errors.

The first unit test will be as following:

<

This unit test makes use of the following fake Database implementation.

To keep this blog post simple, I am not showcasing the TDD steps which I have done here and the EmployeeController Code would be as follows.

Employee Controller makes use of an InMemory Database (Simplest option!!)  which implements the IRepository interface. 

I have done all the wire ups to make the first unit test pass. (Pardon me! For the sake of simplicity of this blog post I’ve violated TDD rules. Hope you can infer the TDD steps from the coding samples). Its time to  move to the next unit test and here comes a bottleneck.    

You may wonder what it is that. There comes a feature of ASP.NET MVC 3 framework. During HTTP post action the framework validates the employee model and sets the EmployeeController’s Property ModelState.IsValid to true or false. It occurs only during HTTP post. In our unit test code we are actually calling the action methods of the controller and not making any HTTP post. So, the ModalState is always true whenever we call the action methods of a controller from a unit testing code. 

In our second test case, we need to setup a controller in such a way that its ModelState property is InValid. We can do this by adding a ModelError to the ModelState property of the EmployeeController. In fact it is what MVC3 framework is doing under the hood when making HTTP post. 

Now we Test drived the controller’s responsibility in the context of model validation. In my next blog post   I’d showcase how to test drive the model validation itself.

Comments