Independently testing models, views and controllersEdit

It is often recommended that you use mock objects and stubs to independently test your models, views and controllers when doing not only Behaviour-Driven Development but any testing of code which follows the MVC pattern. (The original version of this article penned in 2007 started with "I highly recommend"; since then I’ve realized that there are trade-offs involved and the right thing to do is seldom so clear-cut.)

By using mocks and stubs you can:

  • Reduce the interdependence of your models, views and controllers during testing.
  • Eliminate the impact of errors in your models from affecting your controllers and views; that is, failures will occur in one site (the model) rather than in multiple sites, and so will be much easier to track down. The same is true in the other senses as well: errors in the controller will not affect the view or model specs and so on.
  • Start developing your views before your models or controllers are even down (or vice versa; you can start with controllers or models; there is no need to have a full stack in place in order to start testing).

I became convinced of the usefulness of doing this while doing Behaviour-Driven Development with Rails. I was able to start by developing and testing isolated models, views and controllers, starting wherever seemed most appropriate rather than having to get the entire MVC graph in place before I could start testing.

Note that even though this kind of testing is highly desirable, it is not meant to replace higher-level testing (sometimes called functional testing or integration testing; that is, tests which verify that all of the pieces in the MVC design work together as expected) but to complement it.

But one further caveat: although mocks can in theory deliver all of the benefits listed above, they can also bring with them considerable overhead and complexity; that is sometimes setting up the mocks requires so much knowledge about the internal implementation of the objects being mocked, and sometimes the set-up is so much more involved than just using the class directly, that it is better to forget about mocks in some cases. For more information about when and when not to mock, see Mocking in Rails.

See also