Spring Boot: @TestConfiguration не переопределяет компонент во время теста интеграции

У меня есть Bean, определенный в классе, украшенном @Configuration:

@Configuration
public class MyBeanConfig {
    @Bean
    public String configPath() {
        return "../production/environment/path";
    }
}

У меня есть класс, украшенный @TestConfiguration, который должен переопределить этот Bean:

@TestConfiguration
public class MyTestConfiguration {
    @Bean
    @Primary
    public String configPath() {
        return "/test/environment/path";
    }
}

Компонент configPath используется для установки пути к внешнему файлу, содержащему регистрационный код, который необходимо прочитать во время запуска. Он используется в классе @Component:

@Component
public class MyParsingComponent {
    private String CONFIG_PATH;
    
    @Autowired
    public void setCONFIG_PATH(String configPath) {
        this.CONFIG_PATH = configPath;
    }
}

Пытаясь отладить это, я установил точку останова внутри каждого метода, а также в конструкторе класса конфигурации теста. Точка останова конструктора @TestConfiguration сработала, поэтому я знаю, что мой класс тестовой конфигурации создает экземпляр, однако метод configPath этого класса никогда не срабатывает. Вместо этого применяется метод configPath обычного класса @Configuration, а @AutowiredString в MyParsingComponent всегда является ../production/environment/path, а не ожидаемым /test/environment/path.

Не уверен, почему это происходит. Приветствуются любые мысли.

Аннотирован ли ваш тестовый класс @Import(MyTestConfiguration.class)?

Sam Brannen 31.05.2018 16:17

@SamBrannen Этого там не было. И добавление не сработало. Но поменял его на @ContextConfiguration(MyTestConfiguration.class). Однако до сих пор не понимаю, почему аннотация @Primary игнорировалась без ContextConfiguration.

The Head Rush 31.05.2018 17:17

Как описано в справочном руководстве Spring Boot, любые bean-компоненты, сконфигурированные в классе верхнего уровня, помеченном @TestConfiguration, не будут обнаружены посредством сканирования компонентов. Вот почему вы должны явно заявить об этом.

Sam Brannen 31.05.2018 18:23

Если ваш класс, аннотированный с помощью @TestConfiguration, был статическим вложенным классом в вашем тестовом классе, он использовался бы автоматически.

Sam Brannen 31.05.2018 18:24

Если это отвечает на ваши вопросы, я могу сделать это формальным отвечать. ;-)

Sam Brannen 31.05.2018 18:24

@SamBrannen Было бы хорошо. Большое спасибо за помощь и объяснения.

The Head Rush 31.05.2018 19:15

Я обнаружил, что если у вас есть другой класс в @ContextConfiguration(classes=...), @TestConfiguration больше не будет работать. Поэтому вам нужно явно добавить свой класс с конфигурацией в @ContextConfiguration(classes=...).

Valeriy K. 18.01.2019 15:17
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
47
7
45 854
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

Как описано в разделе Определение тестовой конфигурации справочного руководства Spring Boot, любые bean-компоненты, сконфигурированные в классе верхнего уровня, аннотированного с помощью @TestConfiguration, будут обнаружены нет посредством сканирования компонентов. Таким образом, вы должны явно зарегистрировать свой класс @TestConfiguration.

Вы можете сделать это либо через @Import(MyTestConfiguration.class), либо через @ContextConfiguration(classes = MyTestConfiguration.class) в своем тестовом классе.

С другой стороны, если ваш класс, аннотированный с помощью @TestConfiguration, был вложенным классом staticв вашего тестового класса, он был бы зарегистрирован автоматически.

Я пытаюсь провести тест с #TestConfiguration, помещенным в класс верхнего уровня, и с #Import (MyTestConfiguration.class) и без #TestConfiguration, но с #Import (MyTestConfiguration.class). Результат был равным. Значит ли это, что #TestConfiguration бесполезен?

Valeriy K. 14.02.2019 10:21
@TestConfiguration по-прежнему полезен. Пожалуйста, обратитесь к связанной документации для получения подробной информации.
Sam Brannen 15.02.2019 11:04

URL мертв

G_V 17.10.2019 10:58

Я исправил ссылку из-за изменений в документации Spring Boot 2.2. Спасибо

Sam Brannen 18.10.2019 11:29

Я хотел бы повторно использовать @TestConfiguration для нескольких тестовых классов, поэтому наличие абстрактного тестового класса, наследуемого всеми остальными, может быть вариантом. К сожалению, @TestConfiguration не подбирается, если он находится в абстрактном классе, от которого наследуется текущий тест. @SamBrannen это задумано? Как поделиться @TestConfiguration между тестовыми классами?

rilaby 29.11.2020 14:59

Убедитесь, что имя метода вашего фабричного метода @Bean не соответствует никакому существующему имени bean-компонента. У меня были проблемы с именами методов, такими как config () или (в моем случае) prometheusConfig (), который конфликтовал с существующими именами bean-компонентов. Spring пропускает эти фабричные методы тихо и просто не вызывает их / не создает экземпляры beans.

Если вы хотите переопределить определение bean-компонента в своем тесте, используйте имя bean-компонента явно как строковый параметр в аннотации @Bean ("beanName").

это реальный ответ. У меня есть вложенный статический класс с @TestConfiguration, и он не работал. Проблема заключалась в том, что фабричный метод был назван так же, как и фактический компонент.

Sebastian 19.04.2020 23:21

В моем весьма своеобразном случае мне также пришлось добавить @Primary. Иначе бы просто кинул expected single matching bean but found 2.

Aivaras 15.04.2021 18:17
  • Конфигурация теста должна быть явно импортирована в тест через @Import({MyTestConfiguration.class}).
  • Названия методов @Bean в @Configuration и @TestConfiguration должны быть разными. По крайней мере, это имеет значение в Spring Boot v2.2.
  • Также убедитесь, что spring.main.allow-bean-definition-overriding=true, иначе компонент не может быть переопределен.

Ваши 2-й и 3-й маркеры вступают в конфликт друг с другом - механизм переопределения bean-компонентов подразумевает, что имена bean-компонентов совпадают.

rilaby 29.11.2020 14:37

Для меня работал этот код:

  @TestConfiguration // 1. necessary
  public class TestMessagesConfig {

    @Bean
    @Primary // 2. necessary
    public MessageSource testMessageSource() { // 3. different method name than in production code e.g. add test prefix

    }
  }

Другие вопросы по теме