I've migrated my blog

Thanks for visiting my blog. I am no longer maintaining this and I've migrated the blog to my personal domain . If you would like to follow my blog kindly use my new RSS feed

Saturday, August 13, 2011

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 practising 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 practising TDD is totally different! Yes, in theory it is very easy to read and understand TDD. But when you practise 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 passsed 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. Infact it is what MVC3 framework is doing under the hood when making HTTP post. 


Hurrah! Thats it !!

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




                
               

               

                 

7 comments:

  1. thats just my opinion that validation code should not be attribute based because it is not TDD friendly. isn't it better to use FluentValidations or any similar library to create validators and test them in a TDD way (isolated).
    Where as in your code you are testing two things in one test i.e. controller, and model.
    whats your opinion on that?

    ReplyDelete
  2. @Adeel
    The blog posts objective is to test drive the controllers responsibility in the context of model validation. As you said, we shouldn't test two things in a single test. In fact it is the objective of this blog post series. Here i'm testing only the controller's behavior alone. The unit tests just simulate a invalid model and test its equivalent controller's behavior. In my next blog post I'd cover how to test drive model validation.

    ReplyDelete
  3. Very Nice...

    Why don't you give it a thought to write some blogs about TDD steps as well.

    ReplyDelete
  4. why would you need to test the out of the box validation in a unit test? Seems like a decent acceptance test, but not sure of the value here. Thoughts?

    ReplyDelete
    Replies
    1. Good catch.. It is a valid candidate for acceptance test. This blogpost just mention the technique through a unit test. You can leverage this easily in an acceptance test.

      Delete