У меня есть 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.
Не уверен, почему это происходит. Приветствуются любые мысли.
@SamBrannen Этого там не было. И добавление не сработало. Но поменял его на @ContextConfiguration(MyTestConfiguration.class). Однако до сих пор не понимаю, почему аннотация @Primary игнорировалась без ContextConfiguration.
Как описано в справочном руководстве Spring Boot, любые bean-компоненты, сконфигурированные в классе верхнего уровня, помеченном @TestConfiguration, не будут обнаружены посредством сканирования компонентов. Вот почему вы должны явно заявить об этом.
Если ваш класс, аннотированный с помощью @TestConfiguration, был статическим вложенным классом в вашем тестовом классе, он использовался бы автоматически.
Если это отвечает на ваши вопросы, я могу сделать это формальным отвечать. ;-)
@SamBrannen Было бы хорошо. Большое спасибо за помощь и объяснения.
Я обнаружил, что если у вас есть другой класс в @ContextConfiguration(classes=...), @TestConfiguration больше не будет работать. Поэтому вам нужно явно добавить свой класс с конфигурацией в @ContextConfiguration(classes=...).




Как описано в разделе Определение тестовой конфигурации справочного руководства Spring Boot, любые bean-компоненты, сконфигурированные в классе верхнего уровня, аннотированного с помощью @TestConfiguration, будут обнаружены нет посредством сканирования компонентов. Таким образом, вы должны явно зарегистрировать свой класс @TestConfiguration.
Вы можете сделать это либо через @Import(MyTestConfiguration.class), либо через @ContextConfiguration(classes = MyTestConfiguration.class) в своем тестовом классе.
С другой стороны, если ваш класс, аннотированный с помощью @TestConfiguration, был вложенным классом staticв вашего тестового класса, он был бы зарегистрирован автоматически.
Я пытаюсь провести тест с #TestConfiguration, помещенным в класс верхнего уровня, и с #Import (MyTestConfiguration.class) и без #TestConfiguration, но с #Import (MyTestConfiguration.class). Результат был равным. Значит ли это, что #TestConfiguration бесполезен?
@TestConfiguration по-прежнему полезен. Пожалуйста, обратитесь к связанной документации для получения подробной информации.
URL мертв
Я исправил ссылку из-за изменений в документации Spring Boot 2.2. Спасибо
Я хотел бы повторно использовать @TestConfiguration для нескольких тестовых классов, поэтому наличие абстрактного тестового класса, наследуемого всеми остальными, может быть вариантом. К сожалению, @TestConfiguration не подбирается, если он находится в абстрактном классе, от которого наследуется текущий тест. @SamBrannen это задумано? Как поделиться @TestConfiguration между тестовыми классами?
Убедитесь, что имя метода вашего фабричного метода @Bean не соответствует никакому существующему имени bean-компонента. У меня были проблемы с именами методов, такими как config () или (в моем случае) prometheusConfig (), который конфликтовал с существующими именами bean-компонентов. Spring пропускает эти фабричные методы тихо и просто не вызывает их / не создает экземпляры beans.
Если вы хотите переопределить определение bean-компонента в своем тесте, используйте имя bean-компонента явно как строковый параметр в аннотации @Bean ("beanName").
это реальный ответ. У меня есть вложенный статический класс с @TestConfiguration, и он не работал. Проблема заключалась в том, что фабричный метод был назван так же, как и фактический компонент.
В моем весьма своеобразном случае мне также пришлось добавить @Primary. Иначе бы просто кинул expected single matching bean but found 2.
@Import({MyTestConfiguration.class}).@Bean в @Configuration и @TestConfiguration должны быть разными. По крайней мере, это имеет значение в Spring Boot v2.2.spring.main.allow-bean-definition-overriding=true, иначе компонент не может быть переопределен.Ваши 2-й и 3-й маркеры вступают в конфликт друг с другом - механизм переопределения bean-компонентов подразумевает, что имена bean-компонентов совпадают.
Для меня работал этот код:
@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
}
}
Аннотирован ли ваш тестовый класс
@Import(MyTestConfiguration.class)?