sobota, 15 sierpnia 2015

Validation night - FluentValidation vs DataAnnotations

Time to do some model validation on my entities. There are many ways to do that, but most common is using DataAnnotations. I really don't like that solution, because it makes my models so ugly that I have to edit them with eyes closed.

I was wondering about reasonable alternatives and by reasonable I mean 'not writing entire framework from scratch' or even 'do it as small and clean as possible'. First guess was to look for entity mapping based validation, but that lead me into darkness, but searching for fluentapi validation returned library with really promising name FluentValidation. Saving you the trouble, here's the link.
I really liked it thanks to extreme simplicity both in implementation and testing.

Lets start with clean model to see what do we have.
Simple class to describe some person. What do I expect from each of my employees?

  • Name has to be between 2-20 chars
  • FamilyName can be little longer, lets say 2-30 chars
  • must have both of them plus ContactInformation 
I went for multiple assertions in one case to reduce length of code...
...[time passing]...
I have started with DataAnnotations tests and it took me a while to discover some nice way to do that.

Here's my Employee decorated with validation attributes. I don't really care yet about messages that will be displayed on the view, but here's how you can define them (it probably would be good idea to place them in concrete language file).
In the begining I've just wanted to be sure that created instance of Employee is valid so I can proceed with the properties. It would be pain in the ass to write methods for all the scenarios and this is just simple validation of three properties. To make my life easier I have created usefull method IsPropertyValid that takes property name as first parameter and all the following are just generic params so I can pass all the possibilities to check at once. For testing different models that method could be moved to abstract class, but lets stick to that one.
That was quite an excercise, but nice test doesn't mean I'm going to forgive all the attributes in my model (or it's ViewModel, yes you can create different view models for your entities to use different validation for specific scenarios, but nope).
Now the way I liked more. After acquiring FluentValidation I've had to attach it to my application. This is simply done by adding FluentValidationModelValidatorProvider.Configure(); in MvcApplication constructor. (it's hiding under Global.asax)
Next step is to create custom validator inheriting from AbstractValidator
After that I'm ready to test (and happy too, because my model is cleaner than the perfect housewife herself). Now FluentValidation provides with its own assertion methods that verify if validation error will occur if we pass specified value to property defined by Expression. There's just one attribute to add so the model will be validated later on by the controller. So the same Employee but with less garbage inside and its tests. There's one more assertion method, ShouldHaveChildValidator but I didn't see the point using it in this case as ContactInformation is being validated separately by it's own controller. For dessert tests outcome, differences may be interesting if you take performance as priority.

Testing MVC Controllers - invalid models

As you might seen at the previous post, there was part of my Controller I didn't test. What happens when model will be invalid? I have started with uncommenting two tests that I've had already prepared for this scenario.
Then I've added some DataAnnotations to make sure I can create instance of invalid Employee (could create nullable properties describing limbs, but thats not the point here).
As you can see in the tests, there was special field for my invalid, _invalidEntity so I eagerly assigned to it my poor Employee with terribly short family name of "Ni". Excited to have my test complete I quickly did (Ctrl + R, N) which is default in Visual Studio to run test that haven't been yet performed and...they failed.
After debugging it turned out that model won't be validated during the test so ModelState.IsValid will be always true. It turned out that testing this scenario is way easier than I expected. Everything that I've had to do was to add validation error manually before acting. Now I didn't need _invalidEntity anymore, instead of that small method was added to be called in the begining of both tests.
That way I've covered entire Create and Edit methods. After quick check on constructor references I've noticed that I use just one of them so I've got rid of the other two and ran the test. Result shown 94.12% coverage, this time everthing except for disposal method. I like to see how numbers grow so "I'll be back!".

czwartek, 13 sierpnia 2015

Testing MVC Controllers

Couple days ago I started learning MVC. Wonderful how knowledge is available all over internet. Indeed, being master of pen is quite a trick so lets get down to the business. After discovering how MVC is supposed to work and playing around, came the time to get little bit more serious. Unit testing. So what approach default HomeControllerTest was suggesting:
Quite fair. Testing Controllers looks really simple! At first I went for Moq to test my basic operations Create, Update, Delete, GetAll and Find. It went pretty nice, but 300-500ms per test just to make sure that proper method on the repository is called and operate on List<> was a huge waste of time. That's how RepositoryStub got born.
Now that's better, implementing that for concrete class is even easier and needed just to make Find method working as the Controller was using it. I could probably just return any element from _items, but it wasn't much more of an effort and provided me with some more flexibility when testing. Here's implementation for EmployesRepositoryStub
After replacing Moq's fake repository with mine, results were much more satisfying.

But wait! Where are those tests? Well that's another story. My first attempt to cover all the methods (except for dispose, I'll take care of it later) took almost 150 lines of code and way more time trying to exctract some abstraction from it (back the time when it was still Moq). With my brand new, generic RepositoryStub I went for beautiful journey to the far lands, where the abstractions get born from chaos (big thanks to Uncle Bob). Here's ControllerTest
Only thing about that I don't like is how I initialize all the fields in base class, but maybe there'll be some time for that other day. With this test I'll be sure to cover 77.03% of my EmployeeController that is everything except for two other constructors, override dispose method and six more lines that will be tested after I create validation for Employee model. Finally horror of writing all that from scratch or even worse, duplicating such wast amounts of code, everytime I want to have new simple controller, moves out of my sight. Currently I need 11 lines to create new repository stub and exactly 16 for each test, which is at least 100 less to write :]