intermediateDependency Inversion Principle

Why does depending on concrete classes instead of interfaces make unit testing harder?

When a class constructs its own concrete dependencies internally, such as a NotificationService creating a real EmailService inside its own constructor, there is no seam where a test can substitute a fake, controllable version of that dependency. That forces any test of the high-level class to also exercise the real low-level implementation, which might mean an actual network call to an email provider, a real database write, or any other slow, unreliable, or side-effect-producing operation just to verify unrelated business logic. When a class instead depends on an interface supplied from outside, a test can pass in a trivial fake implementation that simply records what it was called with, letting the test verify the high-level class's own logic in complete isolation. This is precisely why mocking frameworks like Mockito can only substitute fake implementations for dependencies that were already typed as interfaces or abstract classes in the production code — they cannot meaningfully mock a dependency the class instantiates and holds as a hardcoded concrete type.

Ready to master this question?

Generate a complete walkthrough — background, the full answer in plain language, a working code example explained line by line, a real-world scenario, common mistakes, and how this same question gets asked in different ways.

Sign in to generate a response

Next Step

Continue to How would you extend a Memento-based undo implementation to also support redo?← Back to all Low-Level Design & Design Patterns questions