If the class is difficult to test don’t blame your test code or deficiencies in mock/test libraries. Instead try very hard to make the class under test easy to test.
Is class hard to test? Then it’s the class itself to blame, never the test code.
The punishment is simple: merciless refactoring.
Yet so many times the test is found guilty and unjustly sentenced to refactoring or improving.
Here are some real-life examples – I saw it, I moaned, I preached (poor soul who paired with me that day):
- Class calls static methods. New patterns of mocking static methods are introduced. Yet another mocking framework (or supporting code) is added. Instead, static class could be refactored into genuine citizen of OO world where dependency injection really does miracles.
Ok, I didn’t really see that one. But I read about it ;)
- Class has many dependencies. The builder is introduced to create instances with properly mocked/stubbed dependencies. The effort to refactor test code and introduce builder could be spend on splitting the class so that it is smaller, has less dependencies and doesn’t need a builder any more.
- Class has many dependencies yet again. The test class is enhanced with bunch of private utility methods to help in setting up dependencies. Yet again I would rather split class under test…
- Test method is huge. Test method is decomposed into smaller methods. Instead I would look at responsibility under the test. Perhaps responsibility/method under test is just bloated and solves multiple different problems. I’d rather delegate different responsibilities to different classes.
All of that goes down to very simple principles I follow.
If I find testing difficult I look for reasons in the class under test. If the test smells I look for reasons in the class under test. Class under test is always guilty until proven.
I’m not saying to stop refactoring test code, I’m saying to focus on class under test. Don’t make test code smarter if you can make the code easier to test. If you spend too much time on figuring out how to test something it means code under test sucks.
For me, the quality of the class is reflected by the clarity and simplicity of its test.
Here are some warnings you can find in the test code.
- too big setup() method
- too many fields
- too big test method
- too many test methods
- too many private utility methods
All of them smell and require refactoring. You can refactor test code, make it smarter and better. You can also refactor code under test so that the test doesn’t have to be smart and becomes simple. Simple code doesn’t smell. Usually. ;)