I had it pointed out to me at the end of last year that I use Mocks too much. I isolate the class under test more than I might need to do. Isolation of a class has the most value at service boundaries. If other classes can safely be included in the test without side-effects, I’m actually testing more than jus the class under test.
This is a bad thing, right? No. Not necessarily. The tests purpose is to prove that the code solves it’s intended purpose. If by including more of the system that this piece of code interacts with, the test will be more tightly coupled to the actual use of the class.
If I isolate the class, non-API breaking changes in other classes might cause the requested system behavior to fail, but my test which tests the class in isolation will still pass. The purpose of my tests should naturally be to detect defects earlier.
As I considered this I went back to the places in our code-base where I feel TDD has really really helped me. And sure enough, almost no mocking in those tests, relying instead on actual objects. For me, this was sort of an eye opener.
How do I work without mock’s then?
One example is to use inheritance. If I isolate all calls to system-boundaries to a single method, I can inherit from the class under test and override that system-boundary specific piece of code. This allows me create “mocked” version of the class without the need for mocking libraries.
*This is called Test-specific subclass. Thank you Patrik! *
This method is even applicable to legacy code where mocking isn’t applicable.
Another example would be to use actual objects all the way, if possible. For databases for example you could create a temporary testing database if you have access to a database server. Depending how you access your data you might even be able to have an in memory database instead of an actual database. While this might mean you need to implement a test-class instead of mocking it. If the API doesn’t change all to often it might save you time compared to mocking.