I’m currently reading “Working Effectively with Legacy Code” by Michael Feathers.
So far, a lot of techniques the book mentions, start with a problem similar to:
“it’s really difficult / it would take too long to get the class into a test harness…”
Then the book goes on to suggest a technique to work-around this problem.
Lately, I’ve been working with Jmockit library and it lets you mock pretty much anything you’d like in a pretty easy way.
In that case, doesn’t it make the aforementioned techniques redundant?
While JMockit does allow you to work around a lot of problems, there are two things you need to consider: it will not work for every language out there and it might simply be the wrong solution.
JMockit relies on a number of techniques that work, but that are not language-independent. While every object-oriented language out there will allow you to pass a class into a method and call a method on that class (dependency injection), not every language will allow you to mock or fake every call made. “Working effectively with legacy code” has samples in Java, but the book isn’t about solving this problem in Java alone. It can be, and is applied, in a variety of languages.
It is also sometimes the wrong solution simply because a testable design is often a good design. Let’s assume that you have a class that contains a number of public methods which all use a single, 100-line long private method to prepare data. Unittesting this one class can be problematic: you want to test the logic in the public methods, but that also involves testing the private method. And testing the private method can only be achieved through the public methods, which makes testing hard. Extracting the private method into a separate class and dependency-injecting it not only makes the class more testable, but also makes the class with the remaining methods clearer: it can be smaller, more focused and easier to understand.