Unit-testing – How to inject test objects when the real objects are created dynamically

dependency-injectionunit testing

I want to make a class testable using dependency injection. But the class creates multiple objects at runtime, and passes different values to their constructor. Here's a simplified example:

public abstract class Validator {
    private ErrorList errors;

    public abstract void validate();

    public void addError(String text) {
        errors.add(
            new ValidationError(text));
    }

    public int getNumErrors() {
        return errors.count()
    }
}

public class AgeValidator extends Validator {
    public void validate() {
        addError("first name invalid");
        addError("last name invalid");
    }
}

(There are many other subclasses of Validator.)

What's the best way to change this, so I can inject a fake object instead of ValidationError?

I can create an AbstractValidationErrorFactory, and inject the factory instead. This would work, but it seems like I'll end up creating tons of little factories and factory interfaces, for every dependency of this sort. Is there a better way?

Best Answer

The simplest change to make your class unit testable is to

  1. (extract the creation code into a new (virtual) method - you already have this)
  2. subclass the tested class, overriding the creation method to create a suitable mock object instead of the real one
  3. write your unit tests :-)

Of course, this is not very nice. But it allows you to cover the class with unit tests, after which you can start refactoring towards the ideal design, without fear of breaking code with deeper changes.

Obligatory reference: Working Effectively with Legacy Code.

About that ideal design it is hard to tell much though, since your example lacks details and context. If you tell us more about what you are aiming to test and what is the role of the tested class, we might be able to help more.

Related Topic