Spring @TestConfiguration влияет на другие классы тестов

#java #spring #spring-boot #spring-test

Вопрос:

У меня есть несколько классов интеграционных тестов, все они импортируют конфигурацию из одного @Configuration класса, который externalApi определенным образом создает издевательский компонент (для иллюстрации, передавая true в качестве аргумента конструктора).:

 @Configuration public class TestConfig {    @Bean  @Primary  ExternalApi externalApi() {  return new MockExternalApi(true); // lt;-- true by default for all test classes  } }  

Но для конкретного класса интеграционного теста мне нужно создать этот компонент по-другому (скажем, передать false в качестве аргумента конструктора). Для этого я попытался использовать @TestConfiguration в статическом внутреннем классе следующее:

 @RunWith(SpringRunner.class) @SpringBootTest("spring.main.allow-bean-definition-overriding=true") @Import(TestConfig.class) @ActiveProfiles("test") public class ExampleIT {   @TestConfiguration  public static class ExternalApiConfig {   @Bean  @Primary  ExternalApi externalApi() {  return new MockExternalApi(false); // lt;-- false for this particular test class  }  }   @Test  public void someTest() {...} }  

Это работает, однако, при одновременном выполнении всех моих классов интеграционных тестов ( maven verify например), когда все тестовые классы выполняются после этого одного перерыва. Поскольку они используют один и тот же контекст, кажется, что после изменения этого компонента он остается измененным (т. Е. с этим false аргументом) и для всех последующих тестовых классов. Я попытался исправить это, используя @DirtiesContext на уровне класса, чтобы контекст можно было перезагрузить для следующих тестовых классов, но это не сработало.

Есть ли способ достичь того, что я пытаюсь сделать?

Примечание: Если я добавлю тот же @TestConfiguration самый статический внутренний класс ко всем другим моим классам интеграционного теста, сделав обратное, т. Е. создав externalApi компонент обратно с true помощью arg, то все они будут работать. Но я, конечно, не хочу этого делать.

Комментарии:

1. Как насчет удаления @Import(TestConfig.class) для этого конкретного теста? Или там есть несколько определений компонентов? Кроме того, не могли бы вы попробовать по externalApi -другому назвать этот интеграционный тест, может innerExternalApi быть . Каким-то образом механизм кэширования контекста Spring должен определить, что вы работаете здесь с другим контекстом.

Ответ №1:

Это похоже на ошибку в весеннем бегуне; @TestConfiguration ее не следует распространять. В качестве обходного пути попробуйте добавить @DirtiesContext в свой тест принудительное обновление.

Ответ №2:

Это работает:

Класс конфигурации:

 // @TestConfiguration // Put this class in a separate file // NB! Do not annotate this class with @TestConfiguration, // or else the configuration will be propagated to other tests! public class UkvServiceTestContextConfiguration {  

Набор тестов, использующий эту конфигурацию:

 @RunWith(SpringRunner.class)  // NB! Do not use a nested static configuration class, use an external configuration class. // Nested static configuration class gets propagated to other tests! @Import(UkvServiceTestContextConfiguration.class)  

публичный класс UkvServiceTest {