Что лучший способ состоит в том, чтобы использовать Guice и JMock вместе?

Я начал использовать Guice, чтобы сделать некоторое внедрение зависимости на проекте, прежде всего, потому что я должен ввести насмешки (использующий JMock в настоящее время) слой далеко от модульного теста, который делает ручную инжекцию очень неловкой.

Мой вопрос - то, что лучший подход для представления насмешки? То, что я в настоящее время имею, должно сделать новый модуль в модульном тесте, который удовлетворяет зависимости, и свяжите их с поставщиком, который похож на это:

public class JMockProvider<T> implements Provider<T> {
    private T mock;

    public JMockProvider(T mock) {
        this.mock = mock;
    }

    public T get() {
        return mock;
    }
}

Передача насмешки в конструкторе, таким образом, установка JMock могла бы быть похожей на это:

    final CommunicationQueue queue = context.mock(CommunicationQueue.class);
    final TransactionRollBack trans = context.mock(TransactionRollBack.class);
    Injector injector = Guice.createInjector(new AbstractModule() {
        @Override
        protected void configure() {
            bind(CommunicationQueue.class).toProvider(new JMockProvider<QuickBooksCommunicationQueue>(queue));
            bind(TransactionRollBack.class).toProvider(new JMockProvider<TransactionRollBack>(trans));
        }
    });
    context.checking(new Expectations() {{
        oneOf(queue).retrieve(with(any(int.class)));
        will(returnValue(null));
        never(trans);
    }});
    injector.getInstance(RunResponse.class).processResponseImpl(-1);

Существует ли лучший путь? Я знаю, что AtUnit пытается решить эту проблему, хотя я отсутствую, как он автоволшебно вводит насмешку, которая была создана локально как вышеупомянутое, но я ищу любого неопровержимый довод, почему AtUnit является правильным ответом здесь (кроме его способности менять DI и платформы насмешки, не изменяя тесты) или если существует лучшее решение выполнения его вручную.

7
задан Yishai 11 January 2010 в 21:14
поделиться

4 ответа

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

di позволит впрыску и построить зависимости текущих классов, поэтому, если вы хотите добавить издевался класс OUT (который эффективно останавливает график зависимости), вам просто нужно передать его. Misko Hevery заявил в одном из Tech Tech Tech Techs, что тесты на подразделение должны быть заселены New , а NULL , потому что их объем локализуется в отдельных методах теста на единицу - я должен согласиться с ним.

Есть ли причина, по которой нужно использовать резинку в тестах, то есть если они не являются функциональными / интеграционными тестами?

не будет ли тестировать работу, если она исключила инжектор? Разве вы не могли бы рефакторовать свой тест к чему-то вроде:

final CommunicationQueue queue = context.mock(CommunicationQueue.class);
final TransactionRollBack trans = context.mock(TransactionRollBack.class);

context.checking(new Expectations() {{
    oneOf(queue).retrieve(with(any(int.class)));
    will(returnValue(null));
    never(trans);
}});

RunResponse r = new RunResponse(queue, trans); // depending on the order
r.processResponseImpl(-1);
12
ответ дан 6 December 2019 в 19:36
поделиться

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

JMock / Easymock - это инструменты, помогающие выполнить модульное тестирование вашего класса. Они бесполезны в интеграционном тесте.

В контексте модульного тестирования Guice перекрывается с JMock / Easymock. Guice заставляет пользователей засорять свой код всевозможными аннотациями (такими как @Inject) для достижения того же результата, что и JMock / Easymock. Я категорически не согласен с Guice в том, как они помогают в тестировании. Если разработчики обнаруживают, что используют Guice вместо JMock / Easymock, они либо не проводят настоящий модульный тест, либо пытаются протестировать классы контроллеров.

Тестирование класса контроллера должно выполняться не на уровне модульного тестирования, а на уровне интеграционного тестирования. Для интеграционного теста очень полезно использовать Jakarta Cactus. При тестировании интеграции у разработчиков должны быть доступны все зависимости, и, следовательно, нет необходимости использовать Guice.

В заключение, я не вижу причин использовать Guice для тестирования продукта. Google Guice может быть полезен в разных контекстах, кроме тестирования.

1
ответ дан 6 December 2019 в 19:36
поделиться

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

Я потратил некоторое время на то, чтобы прочитать ваш код, опубликованный в начале (обычно я этого не делаю), просто чтобы понять, почему вы сказали, что модульное тестирование вашего класса невозможно. Я наконец понял, с какой проблемой вы столкнулись. Насколько я понимаю, на уровне модульного тестирования вы пытались имитировать поток выполнения фрагмента кода, когда он выполняется на сервере Java EE. Вот почему вы застряли. Я не знаю, каков здесь стимул, но боюсь, что ваши усилия по подготовке всех этих зависимостей среды будут потрачены впустую: (

Написание модульного теста - это проверка «бизнес-логики», которая не зависит от чего-либо технологии, которую вы используете. Может существовать дополнительное требование о том, что эта бизнес-логика должна выполняться в среде Quality of Service (QoS) . Это требование является «техническим требованием». В вашем примере CommunicationQueue и TransactionRollBack в основном функционируют, чтобы удовлетворить «техническое требование». Ситуация такова, что ваше «бизнес-требование» окружено всеми этими средами.Что вам следует сделать, так это провести рефакторинг вашего кода, чтобы ваше «бизнес-требование» находилось в отдельных методах, не имеющих зависимостей. Затем вы пишете модульный тест для этих методов.

Я все еще считаю, что вы проводите функциональное тестирование. Проведение функционального тестирования на уровне модульного тестирования занимает очень много времени, да и не стоит этого делать. Надеюсь, это поможет

0
ответ дан 6 December 2019 в 19:36
поделиться

Yishai, похоже, вам нужен AOP, чтобы обойти эти зависимости. AspectJ и AspectWerkz - оба полезные ресурсы. Однако у AspectWekz есть очень хорошая функция переплетения классов аспектов во время выполнения с использованием технологии горячей замены JVM. Конечно, эти инженерные усилия должны применяться только на уровне модульного тестирования.

Я приложил много усилий для разрешения зависимостей при проведении модульного тестирования. Такие инструменты, как JMock, EasyMock, микроконтейнер Java EE, AspectJ, AspectWerkz, Spring IoC могут быть использованы для решения проблемы DI. Ни один из этих инструментов не побуждает разработчиков внедрять осознанность тестирования в производственные коды. Очень жаль, что Guice нарушает концепцию сохранения кода чистым от любого рода осознания тестирования. И я не считаю его инструментом для использования в юнит-тестировании.

Надеюсь, я дал вам достаточно причин, чтобы убрать аннотацию @Inject из вашего производственного кода.

0
ответ дан 6 December 2019 в 19:36
поделиться
Другие вопросы по тегам:

Похожие вопросы: