skip to content
16 June 2013

You should unit test your controller, NOT!

Unit Testing MVC

Unit testing per se is a controversial topic, what you should unit test is another controversial topic. The topic of this post started by a short conversation during a .NET London Group meeting back in 2010, I thought about it and then gave it more thoughts, I started using it in my projects, then now I have enough confidence to share my thoughts. Here is my opinion, if you agree or disagree, then please do comment.

Controllers should be slim

You’ve heard this before: “Controllers shouldn’t be fat, controllers should contain minimal code”, it’s a mantra.

The S in SOLID stands for SRP. A controller should have one role, it is the communication layer between a model and a view. Even with this role, it is violating SRP, one could say maybe we need two classes to take the role of a controller or a controller per action method, but let’s not delve into that.

The controller, by role, is overloaded with responsibilities, adding more responsibilities to it is a design crime (maybe one should be penalised by losing some StackOverflow or CodeProject points 🙂 ).

Why do controllers get fat?

I did blog earlier on how views become fat Three Steps to Get Fat-Razor MVC Views on Diet, some points are common and some are specific to controllers:

Explicit validation of data in the action method

Validation of your viewmodel data in your controller violates two principles:

  1. SRP Design Principle: You are attaching more responsibilities to the controller.
  2. Encapsulation OOP Principle: You will have to expose your data outside your viewmodel to allow another object, the controller, to validate it, while the object itself should be responsible for its own data.

ASP.NET MVC 4 has a good validation ecosystem that will help you moving your validation code to where it belongs.

Mapping a model to a viewmodel

The mapping from a model to a viewmodel should not be done in the action method. My favourite solution is to use a CQRS type query pattern so I don’t have to do this boilerplate anywhere. Here is a good Introduction to CQRS.

Leaking some business logic

This is not a place for any business logic. The controller should be calling a service, of a classical DDD implementation, or issuing a query or a command of CQRS.

Http-related code in the action method

Having a special HTTP case that requires special handling should not be done here. Action filters might be the answer.

What are you unit testing?!

Given the above and if your action methods have almost no code, then what are you unit testing? Do you want to test if you are returning the proper view or do you want to test if you have decorated your action method with the proper attributes? I wouldn’t, I usually have a deadline to hit and I am against boilerplate code.

If someone tells me their controller requires unit testing, I will ask, did you design your controller properly?


Unit testing is a mean for providing higher quality software and not an aim per se. Having too many redundant unit tests will cause a future maintenance headache and will cost more project development time.

If an area/layer requires unit testing then you should probably test it, but for other areas more tests may be less quality.

Update – I told you not to unit test your controllers, by keeping them empty, here is one way to keep your controllers thin: Implementing a CQRS-based Architecture with MVC and Document DB.

leave your own
  • Óscar Sotorrío October 29th, 2013

    Hi Adam,

    I have to admit that it is an interesting point of view. But I still wonder about something.

    You have talked about unit test in general terms but you haven’t commented if tests are verified as state or behavior.

    Could be interesting to test if the controller makes a specific call?. What do you think about that?. In your opinion, should we verify behavior controller?


  • Chris Emerson November 19th, 2013

    “A controller should have one role, it is the communication layer between a model and a view. ”

    Can’t agree with this – the controller should instantiate both the view and any models needed depending on the route / input parameters, but the views should then access the models directly and handle and communication between them. The controller shouldn’t be a ‘mediator’ that separates them – MVC says that the view should take what it needs from the models and display it. In a web application this is a one time thing, but in a desktop/stateful application the view is updating all the time based on changes notified from the models.

  • Dheeraj November 22nd, 2013

    I agree with you their is no need to do unit testing for controller but what about Model.

    If it is require to do unit testing for Model then can share with me any examples


  • Dan pupek February 6th, 2014

    I have to disagree. I do agree with chris. The controller is more than just a middle man. You should have business logic in their.

  • Suresh.C February 18th, 2014

    One of the core objective of MVC pattern is enabling testablity on the presentation layer, especially verigy the logic in controller. What else?

  • Rick August 28th, 2014

    The controllers should never have business logic in them. You should have a service layer for that and then unit test that service layer. The biggest controller I have is probably 7 lines and exists to do minimal clue code between the service and view.

    Why you may ask have a service layer doing the business logic vs the controller? Because that business logic may need to be exposed in different applications and having it in it’s own service layer (which for me is it’s own DLL project) you can move it around and reuse it. Controllers can’t be moved around to another project or easily have them wrapped into a web api. You never know what functionality will be required by different applications and by having your own service layer, you’ll be able to reuse them very easily.

  • Jan June 30th, 2015

    Rick is absolutely right.

    But you don’t have to have multiple applications to profit from business-logic-free-controllers. Even if you have only one application the encapsulation of business logic in a service encourages reusability in that single application.

  • Vlad July 2nd, 2015

    I disagree. It’s not what is inside your unit that should be tested but how your unit is seen and interacted with by the outside world. I do not particularly care if the unit is implemented using mvc or not. I just need to know how to talk to it. This way I am decoupling my testing from my implementation.

  • j September 23rd, 2015

    Adam, You are just moving the Controller from what is called ‘Controller’ in the Microsoft’s MVC. In this sens you are right… But what is really happening is, that the Controller is being moved to the CQRS architecture and you are testing it. Conclusion is that you are testing MC, but somewhere else.

  • Matt DuFeu February 18th, 2016

    Slightly off topic, but this got me thinking a lot about Unit Testing ROI.

    I see teams strive for a certain % of code coverage and don’t seem to care what they test, just as long as the line is tested.

    100% of code coverage on a thin controller is pointless. Your post helped me convince someone of this. Thank you!

  • Unit Testing - Check your Return on Investment - Matt DuFeu February 29th, 2016

    […] Adam Tibi got me thinking about it a lot recently when I read his post on not testing MVC controllers. […]

  • Alexander May 31st, 2016

    Matt, thanks for pointing it out. Code coverage is important in business code, not in plumbing one. Sorry, but I can’t see gain in verifying whether the Controller makes a call to the service layer or not.

Leave a Reply