Dependency Injection by Extension pattern

The problem

You need to use some kind of Dependency Injection (DI for short) to provision some System Under Test (SUT for short) in tests you’re writing, but can’t or don’t want to use a DI framework to do so.

Alternative titles for this post include:

  • Dependency Injection without a Dependency Injection framework
  • Why misusing the default namespace for tests is evil
  • Make code more testable without completely messing it up

I’m not sure whether I have indeed invented a new design pattern here. Read on and let me know.

Don’t expose your privates

Of course, the simplest form of DI is simply passing things to a constructor. But you probably don’t want to code every class to be handed every dependency at construction. And you definitely don’t want to expose the private parts of your implementation through some unnecessary interface. No, you really don’t!


 

I’ve seen scary examples of what I call ‘keyhole surgery’ on classes, either by abuse of the internal namespace to allow poking into otherwise private implementation, or just by making too many things public. Although the internal namespace (AKA the default namespace) is perceived to retain a sufficient level of encapsulation, it really doesn’t. Anything in the same package can jump all over it, so it’s somewhat of a loose interface. As such, you should never leave methods unscoped, letting them default to the internal namespace. You should also reserve the internal namespace only for when you are in control of all classes that will exist in the same package, such as when creating utility classes.

Loose interfaces are bad practice for a few reasons:

  • Clarity – anyone using the class will be confused as to the intentions of its interface
  • Stability – a class with such a loose interface is open to misuse and a recipe for failure
  • Cleanliness – code for tests does not belong in your production code
  • Testability – you should test a class through its interface, not its implementation
  • Flexibility – it is hard to refactor classes that leak implementation detail in such a way

The solution

Well, this is one possible solution and ultimately just my suggestion. It’s especially useful when needing to refactor classes with overuse of the internal namespace, since you won’t need to change much test or production code. I call it the Dependency Injection by Extension pattern.

How it works

You provide DI helpers as protected methods in your SUT and subclass it from within your test case, as a script-level class, to expose the DI helpers as public and/or use the constructor to do some of the DI work – allowing you to inject mocked dependencies for your tests. This has the advantage of not allowing anything else to meddle with your SUT, other than through its interface, of course. And, if anything in your production code wishes to extend your SUT, potentially overriding and messing up the interface, then that class should have its own tests anyway.

Example

The following example shows a very basic class (SystemUnderTest) being extended from within its testcase (SomeTest) to allow injection and access to its dependencies, for the purpose of verifying its behaviour under given conditions.

InterServer Web Hosting and VPS
 

Leave a Reply