Unit testing with ruby (part 3)

Here follows a dummy controller scenario :

While testing this method is certainly possible, given that both @view and @service are injected at some point before the callback is fired, tests are not going to be lean :

Mock objects are a necessary evil: when there’s no output to check and no clean way to access the modified state you can check for the correct calls to be made on your mocks. Sure, it looks better than no testing at all, but the price to pay is pretty high:

  • Verifying expectations means testing how and not what, which is what you really care about.
  • The tests become much less valuable since they are almost useless as documentation: it takes much less to go straight into the code than to understand what’s going on from reading an integration test.
  • The majority of the test code will be about setting up the environment. In the example the only 2 lines we care about are the one where the expectation is set and the last one, the actual method call on the controller. All the remaining code is just to allow the method to execute.
  • By the fact that you’re testing how mocking basically means duplication of your under-test logic. Adding insult to injury it also makes your tests extremely frail, because even a single change in your logic will reflect into lot of broken tests due to setups not working anymore.

When mocking becomes a source of too much hassle it’s often useful to stop testing and reconsider the code under test: there’s a good chance something ‘s wrong with the underlying design, much likely too much work is done by a single actor, usually the controller (or presenter, viewmodel, you pick it). For instance, assuming that the view mechanics are a given and cannot be modified, the example code would be a little better if refactored to be like this:

Controller methods should be a maximum of three line long, with no ifs. No kidding! I also drop the testing completely on controllers if i can get methods that simple: they add no value and are a pain to keep green, especially on the first stages of development.
In the end i think it’s important to remember that mocking (and unit testing, agile and what else) is just a tool and by the moment it gets in your way you should carefully reconsider what the benefits are: methodology is always out there looking for a chance to strike, don’t let your guard off 🙂

Leave a comment