Should controllers in MVC web applications be unit-testable? Should controllers in MVC web applications be unit-testable? php php

Should controllers in MVC web applications be unit-testable?


Short answer: "Yes" with an "If," long answer: "No" with a "But."

These days I tend to miss controller-level unit tests in favour of strong unit-test coverage of models and business objects and functional-test coverage with Cucumber. The assumption here is that the controllers are very light-weight objects routing data into underlying models that encapsulate the vast majority of business logic.

However, I still do tend to have some very light coverage of some of the control flow at the controller level. It just tends to be more of a sanity-check.

One of the issues with controller-level testing is that you often either have to mock or generate a large number of models and objects in order to test effectively. Given this, I find it more valuable to push these tests up into the functional layers where the style of testing allows you to more efficiently express these dependencies (either by explicitly following the steps required to generate them through your application itself or through a system like Cucumber's declarative rules).


Everything is worth to be unit tested. In this case it depends on how much of the logic is realized in the controllers... In small project you can have no external logic attached and you may want to make some of the database operations in your controller (like on many Microsoft examples). In bigger solutions you may not need to test the controller as far as it's job is just to invoke specified business logic methods... It's not about if controllers are worth to be unit tested, it's about if the code that they contains is...


One of the best features of the MVC pattern is that the controllers can be tested in isolation of the HTML output by the views. Pages that mix the logic with the HTML output are hard to test, and this is one of the problems that MVC solves - it makes your controller all about logic and you can test it without parsing HTML at all.

Ideally, your controller will get data from separate data access classes, which you can stub out for your tests, so you are just testing the logic. Essentially you isolate your controller from the database in the same way MVC isolates it from the view - then the tests are easy because you don't need a database with test data either.