I often use the terms “mocking” and “dependency injection” interchangeably. Now, I know that they are different, however, given that a mock object assumes some sort of dependency injection is involved, I hope you’ll forgive me. However, dependency injection without mocking of some sort implies that you’re not unit testing, and that’s just plain wrong.
Also, we could actually be talking about an isolation framework where we are able to present substitute objects for those objects that can’t normally be mocked (like TypeMock or Microsoft Fakes Shims) and still loosely refer to that as mocking.
So when do we choose to mock (either classic mock/stub or isolation) and when should we leave well enough alone to avoid mucking up the design?
Let’s take a classic object-oriented example, such as with a “Car” object. A car object might have an engine object, and electrical system object, wheel objects, etc. In the simple case, we’d want to leave it alone and not introduce a bunch of mock objects. By “simple case”, we mean that there is no need to have special classes that represent a carbon fuel engine, another class to represent an electric engine, and yet another class that might represent a “hybrid” engine, which might all represented by an IEngine interface (in the case of C#). By the way, if there’s no immediate requirement for such an IEngine interface, but you think it might be useful in the future, just hold on, hombre – You aren’t gonna need it (YAGNI). Don’t add code unless it’s required, and make it as simple as possible.
So in the case of a simple Car object and a simple Engine object, just skip mocking the engine. Introducing dependency inject is not “as simple as possible”, but rather, it introduces additional complexity.
“But, but, but… who’s going to create the Engine object?” you might ask in a querulous voice. Simple (see what I did there?), let the Car create the engine.
(Gasp!)(sputter!) “But that’s agile and object oriented blasphemy!” Meh… not so much. Remember, this is just a simple set of objects, which is how it should always start out. Until dependency injection is an actual requirement (and one that’s not simply in your own mind), You Aren’t Gonna Need It!
In the case of simple component objects, let the composite object construct its own simple component objects. Your tests should become much simpler.
You say, “But then I am not isolating my unit tests to a single object! How will I know where something breaks?” Well, given that you’re practicing TDD (and you are, aren’t you), then you’ll know that the problem was with the last few lines of code you just wrote.
“So, then it is better to not mock at all,” you may well say. But let’s not throw the baby out with the bathwater, as the saying goes. There are plenty of situations where dependency injection and mock objects are useful.
Bottom line, if you’re introducing an interface for no other reason other than it’s what you always do when testing, then please reconsider. Is there a way to simplify your design such that it doesn’t require mocks? But if you’re:
- working with interfaces for more than just testing reasons (mock/stub),
- or your component objects cross process boundaries (mock/stub),
- or calls against your component have are not idempotent (likely shim)
…then by all means, use dependency injection or a shim.