In regards to my previous post about Mock Objects and their inherent problems, Scott writes this comment:
"I particularly like the technique where a virtual method allows the unit tests to subclass and inject dependencies. I feel this is an elegant solution compared to dependency injection with constructors. I was wondering if you had rules of thumb on when to use one versus the other? "
"Inherit & Override" is a great method I use especially in these cases:
- When there is complex logic (usually validation logic including many "flags" in a method. I then delegate each "question" in the method to a virtual method which allows me to simulate very complex logical situations and see whether the method logic behaves correctly.
- When dealing with legacy code this is a great way to break dependencies without introducing new interfaces and still allowing a "poor man's" interaction testing. The trick here is to make sure that you only put in the virtual function the smallest piece of code that talks to an outside dependency without any logic. This could be a mere call to a Singleton object (making a function called "getObject" virtual ) or a call to "mailer.SendEmail(param1,param2)".
- When trying to remove any performance bottlenecks from the application. For example, an application that times out on specific calls, I would either remove the calls, or change the timeout duration by a parameter or an overridden method that returns the duration required.
Overall - this is a great way to break dependencies in your tests and people should be aware of it. Mock objects are not everything. However, it usually requires more code but allows for pretty elegant tests to be created.
- I've demonstrated a few techniques relating to inherit and override at the Agile Israel user group. The download is available including code sample over here.
- Michael Feathers' book "Working effectively with Legacy code" is a great resource with many examples of deep investigations in to the world of "how do I bend my code to make it testable?"