Как внедрение зависимостей способствует тестируемости

Я читал о шаблоне Factory и наткнулся на статьи, в которых предлагается использовать шаблон Factory в сочетании с внедрением зависимостей для максимальной возможности повторного использования и тестирования. Хотя мне не удалось найти никаких конкретных примеров этого гибрида Factory-DI, я собираюсь попробовать и привести несколько примеров кода моей интерпретации . Однако на самом деле мой вопрос заключается в том, как этот подход улучшает тестируемость.

Моя интерпретация:

Итак, у нас есть класс Widget :

public class Widget {
    // blah
}

И мы хотим включить WidgetFactory для управления построением Widget s:

public interface WidgetFactory {

    public abstract static Widget getWidget();
}

public class StandardWidgetFactory implements WidgetFactory {

    @Override
    public final static Widget getWidget() {
        // Creates normal Widgets
    }
}

public class TestWidgetFactory implements WidgetFactory {

    @Override
    public final static Widget getWidget() {
        // Creates test/mock Widgets for unit testing purposes
    }
}

Хотя в этом примере используется Spring DI (это единственный API, с которым у меня есть опыт), на самом деле не имеет значения, говорим мы о Guice или какой-либо другой инфраструктуре IoC; идея здесь в том, что теперь мы собираемся внедрить правильную реализацию WidgetFactory во время выполнения в зависимости от того, тестируем ли мы код или работаем нормально. В Spring конфигурация beans может выглядеть так:





Затем в коде:

WidgetFactory wf = applicationContext.getBean("injected-factory");
Widget w = wf.getWidget();

Таким образом, переменная среды (уровня развертывания), возможно, определенная в .properties где-нибудь, решает, будет ли Spring DI внедрять StandardWidgetFactory или TestWidgetFactory .

Правильно ли я делаю?!? Кажется, ужасно много инфраструктуры просто обеспечивает хорошую тестируемость для моего виджета . Не то чтобы я против этого, но мне это просто кажется чрезмерной инженерией.

Мое зависание:

Я спрашиваю об этом потому, что у меня будут другие объекты в других пакетах, в которых есть методы, использующие объекты Widget внутри них. Возможно, что-то вроде:

public class Fizz {
    public void doSomething() {

        WidgetFactory wf = applicationContext.getBean("injected-factory");
        Widget widget = wf.getWidget();

        int foo = widget.calculatePremable(this.rippleFactor);

        doSomethingElse(foo);
    }
}

Без этой огромной, казалось бы, чрезмерно сложной настройки у меня не было бы возможности внедрить «mock Widgets » в свой модульный тест для Fizz :: doSomething ( ) .

Итак, я разорван: с одной стороны, мне кажется, что я слишком много думаю о вещах - что я вполне могу делать (если моя интерпретация неверна ). С другой стороны, я не вижу никакого чистого способа обойти это.

В качестве перехода к второстепенному вопросу это также вызывает у меня еще одно огромное беспокойство: если моя интерпретация верна (или даже в некоторой степени верна), значит ли это, что нам нужны Фабрики для каждого объекта ?! ?

Похоже на чрезмерную инженерию ! Какая отсечка? Какая черта на песке определяет, когда использовать Фабрику, а когда нет ?! Спасибо за любую помощь и извинения за подробный вопрос. У меня просто кружится голова.

6
задан IAmYourFaja 20 December 2011 в 15:50
поделиться