Внедрить моки JMockit в контекст Spring

Для некоторых интеграционных тестов мы используем @ContextConfiguration Spring для создания реального контекста Spring во время теста. Теперь это не должно быть полным интеграционным тестом, поэтому нам нужна целая куча бинов Spring в качестве макетов. Это не слишком сложно, если использовать Mockito и фабричный метод Spring, и еще проще с Springockito.

Но это использует Mockito, а мы просто переходим на JMockit. Я бы предпочел использовать JMockit и здесь. По сути, я ищу замену Springockito, которая вместо этого использует JMockit.

Я тоже умею руками. Тем не менее, Mockito и JMockit, кажется, отличаются в одном очень важном аспекте: в то время как в Mockito вы создаете макеты императивно, используя вызов метода, в JMockit вы получаете макеты, декларативно «внедряемые» в ваш тест. Слишком поздно заполнять контекст Spring. Так что, если кто-то может ответить на этот вопрос, я тоже буду рад: как вы можете создать макет в JMockit в своем коде?


person Michael Piefel    schedule 23.10.2015    source источник


Ответы (2)


Если вы используете Spring Test для выполнения всех инъекций, вы можете просто позволить ему выполнять работу по созданию экземпляров для всех зависимостей, в то время как они имитируются с помощью подходящих фиктивных полей/параметров, объявленных с помощью аннотаций @Mocked или @Capturing. Последний будет имитировать любой класс реализации, который Spring выбрал для создания экземпляра, даже если тип, используемый в фиктивном объявлении, является интерфейсом или базовым классом.

В качестве альтернативы вы можете просто позволить JMockit самому разрешать все зависимости, используя @Tested(fullyInitialized = true) для проверенных объектов верхнего уровня, с фиктивными зависимостями, предоставленными как @Injectable.

person Rogério    schedule 23.10.2015
comment
Это не работает. Spring создает контекст до запуска JMockit и перезаписывает конструкторы. - person Michael Piefel; 27.10.2015
comment
Что касается использования fullyInitialized — это, безусловно, правильно, когда все, что вам нужно от Spring, — это DI, но в моем тесте мне нужна конфигурация веб-приложения для тестирования контроллеров MCV. - person Michael Piefel; 27.10.2015
comment
Почему это имеет значение, если Spring создает bean-компоненты до того, как над ними будут издеваться? Они выполняют какой-то код, который терпит неудачу или что-то в этом роде? - person Rogério; 27.10.2015
comment
Бин, инициализированный Spring, может выполнять код в @PostConstruct, и они также являются целью для автосвязывания (им нужны свои зависимости, чтобы они существовали). - person Michael Piefel; 28.10.2015
comment
Да, в самом деле. Это может быть проблемой, если вам нужно смоделировать зависимости, используемые в @PostConstruct; на практике это должно быть очень редко. - person Rogério; 28.10.2015

«Грязный» трюк, который мы используем с Spring и интеграционными тестами, когда нам все еще нужно что-то смоделировать, заключается в замене, где это необходимо, реальной конфигурацией, например.

@Configuration
@Profile("!test")
public class MyConfig {
    @Bean
    public MyBean bean() {
        /** Real bean **/
    }
}

с фиктивным

@Configuration
@Profile("test")
public class MyTestConfig {
    @Bean
    public MyBean bean() {
        final MyBean bean = mock(MyBean.class);
        when(bean.doSomething()).thenReturn(withReply());
        return bean;
    }
}

он работает с «настоящим» контекстом Spring Integration Test и Mockito, он должен работать и с JMockit, если вы можете создать свой bean-компонент с версией JMockit вашего класса: в основном что-то эквивалентное mock(MyBean. класс).

Изменить: хотя я не знаком с JMockit, кажется, что эквивалентный способ может быть

@Configuration
@Profile("test")
public class MyTestConfig {

    @Injectable MyBean mockXyz;

    @Bean
    public MyBean bean() {
        /** You can probably mock its behaviour **/
        return mockXyz;
    }
}
person m c    schedule 23.10.2015
comment
Мне кажется, что в JMockit действительно нет эквивалента mock(MyBean.class). - person Michael Piefel; 23.10.2015
comment
Несмотря на то, что тестовый класс может быть своим собственным классом конфигурации в тесте Spring (что выглядит ошеломляюще), на тот момент JMockit еще не включился. Другими словами, аннотация @Injectable еще не имела никакого эффекта, mockXyz это null. - person Michael Piefel; 23.10.2015