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.
#1 by Håkan Forss on January 12, 2010 - 10:08
I think you just use the mock frameworks wrong. You are mocking things that should be part of the system under test just as you state.
Your sugested solution is just a way to mock without using a mock framework. Why would you not use a tool that help you do the same job but faster.
#2 by Morten on January 12, 2010 - 10:12
Hi Håkan!
The point is to consider if mocking really is the “fastest” tool for the job when writing the test. I’m not saying “don’t use mocking libraries”, I’m saying “consider not using mocking libraries, instead of just opting for using them”.
Depending on how you design you classes Mocking tools might just increase the burden, making it less clear what is under test, or just adding unnecessary coupling to mocking frameworks.
But yes, there are instances where you can get good results from a mocking framework. Just don’t mock blindly.
#3 by Johan A/ndersson on January 12, 2010 - 20:45
My discovery when we removed Rhino mocks was that we could swap services (such as an IDbConnection) the SUT used. The result is test cases separated from the arrangement of the SUT dependencies (again, such as the behavior/expectations of a database interface).
When arranged like this you could easily write ONE set of test cases for both unit and integration tests.
You can still use Rhino Mocks (or something else), but you will need to place your setup/expectations separate from your test fixture.
Then you need a mechanism to switch from mocked or non-mocked dependencies, perhaps different concrete test fixtures injecting the SUT dependencies using overridden abstract methods or something.
#4 by Patrik Akselsson on January 12, 2010 - 22:51
I think the pattern you are looking for is “Test specific subclass”, http://xunitpatterns.com/Test-Specific%20Subclass.html