Как использовать @ComponentScan вместе с конкретными контекстными настройками теста в SpringJunit4TestRunner?

Я тестирую приложение Spring Boot. У меня есть несколько тестовых классов, каждый из которых нуждается в различном наборе фиктивных или иным образом настроенных bean-компонентов.

Вот эскиз установки:

SRC / Основной / Java:

package com.example.myapp;

@SpringBootApplication
@ComponentScan(
        basePackageClasses = {
                MyApplication.class,
                ImportantConfigurationFromSomeLibrary.class,
                ImportantConfigurationFromAnotherLibrary.class})
@EnableFeignClients
@EnableHystrix
public class MyApplication {
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

package com.example.myapp.feature1;

@Component
public class Component1 {
    @Autowired
    ServiceClient serviceClient;

    @Autowired
    SpringDataJpaRepository dbRepository;

    @Autowired
    ThingFromSomeLibrary importantThingIDontWantToExplicitlyConstructInTests;

    // methods I want to test...
}

SRC / тест / Java:

package com.example.myapp;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MyApplication.class)
@WebAppConfiguration
@ActiveProfiles("test")
public class Component1TestWithFakeCommunication {

    @Autowired
    Component1 component1; // <-- the thing we're testing. wants the above mock implementations of beans wired into it.

    @Autowired
    ServiceClient mockedServiceClient;

    @Configuration
    static class ContextConfiguration {
        @Bean
        @Primary
        public ServiceClient mockedServiceClient() {
            return mock(ServiceClient.class);
        }
    }

    @Before
    public void setup() {
        reset(mockedServiceClient);
    }

    @Test
    public void shouldBehaveACertainWay() {
        // customize mock, call component methods, assert results...
    }
}

package com.example.myapp;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = MyApplication.class)
@WebAppConfiguration
@ActiveProfiles("test")
public class Component1TestWithRealCommunication {

    @Autowired
    Component1 component1; // <-- the thing we're testing. wants the real implementations in this test.

    @Autowired
    ServiceClient mockedServiceClient;

    @Before
    public void setup() {
        reset(mockedServiceClient);
    }

    @Test
    public void shouldBehaveACertainWay() {
        // call component methods, assert results...
    }
}

Проблема с вышеупомянутой настройкой состоит в том, что сканирование компонента, настроенное в MyApplication, выбирает Component1TestWithFakeCommunication.ContextConfiguration, поэтому я получаю фиктивный ServiceClient даже в Component1TestWithRealCommunication, где мне нужна реальная реализация ServiceClient.

Хотя я мог бы использовать конструкторы @Autowired и создавать компоненты самостоятельно в обоих тестах, существует достаточно вещей со сложной настройкой, для которых я бы предпочел настроить Spring TestContext для меня (например, репозитории Spring Data JPA, компоненты из библиотек вне приложения, которые извлекают компоненты из контекста Spring и т. д.). Вложение конфигурации Spring внутри теста, которая может локально переопределять определенные определения bean-компонентов в контексте Spring, кажется, что это должен быть чистый способ сделать это; единственный недостаток заключается в том, что эти вложенные конфигурации в конечном итоге влияют на все тесты Spring TestContext, основанные на их конфигурации на MyApplication (какой компонент сканирует пакет приложения).

Как мне изменить мои настройки, чтобы я по-прежнему получал «в основном реальный» контекст Spring для своих тестов, используя только несколько локально переопределенных bean-компонентов в каждом тестовом классе?

Ответы на вопрос(4)

Ваш ответ на вопрос