Порядок обработки @Import
классов при их использовании в тестах не определен. Функция @Import
для тестов была в первую очередь добавлена для упрощения регистрации дополнительных bean-компонентов, она не предназначалась для использования замены определений bean-компонентов.
Если вы хотите покопаться в зарослях и посмотреть, что именно происходит, вы можете открыть ConfigurationClassParser
и добавить условную точку останова в doProcessConfigurationClass
. Добавьте следующий код условия:
System.err.println(configClass);
return false;
Теперь, если вы отлаживаете приложение, вы получите дополнительный вывод по мере обработки классов конфигурации.
При использовании атрибута аннотации classes
без @Import
вы увидите:
ConfigurationClass: beanName 'demoImportBugApplication', com.example.demoimportbug.DemoImportBugApplication
ConfigurationClass: beanName 'original', class path resource [com/example/demoimportbug/first/Original.class]
ConfigurationClass: beanName 'workerConfig', class path resource [com/example/demoimportbug/first/WorkerConfig.class]
ConfigurationClass: beanName 'null', class path resource [org/springframework/scheduling/annotation/ProxyAsyncConfiguration.class]
ConfigurationClass: beanName 'null', class path resource [org/springframework/scheduling/annotation/ProxyAsyncConfiguration.class]
ConfigurationClass: beanName 'someTestSecondConfiguration', com.example.demoimportbug.second.SomeTestSecondConfiguration
ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/context/PropertyPlaceholderAutoConfiguration.class]
ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/task/TaskExecutionAutoConfiguration.class]
ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/cache/CacheAutoConfiguration.class]
ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/cache/GenericCacheConfiguration.class]
ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/cache/SimpleCacheConfiguration.class]
ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/cache/NoOpCacheConfiguration.class]
ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/context/ConfigurationPropertiesAutoConfiguration.class]
ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/info/ProjectInfoAutoConfiguration.class]
ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/task/TaskSchedulingAutoConfiguration.class]
Когда вы используете @Import
без атрибута classes
, вы получите:
ConfigurationClass: beanName 'org.springframework.boot.test.context.ImportsContextCustomizer$ImportsConfiguration', org.springframework.boot.test.context.ImportsContextCustomizer$ImportsConfiguration
ConfigurationClass: beanName 'null', class path resource [com/example/demoimportbug/first/SomeFirstUsingSecondConfiguration.class]
ConfigurationClass: beanName 'null', class path resource [com/example/demoimportbug/second/SomeTestSecondConfiguration.class]
ConfigurationClass: beanName 'demoImportBugApplication', com.example.demoimportbug.DemoImportBugApplication
ConfigurationClass: beanName 'original', class path resource [com/example/demoimportbug/first/Original.class]
ConfigurationClass: beanName 'workerConfig', class path resource [com/example/demoimportbug/first/WorkerConfig.class]
ConfigurationClass: beanName 'null', class path resource [org/springframework/scheduling/annotation/ProxyAsyncConfiguration.class]
ConfigurationClass: beanName 'null', class path resource [org/springframework/scheduling/annotation/ProxyAsyncConfiguration.class]
ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/context/PropertyPlaceholderAutoConfiguration.class]
ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/task/TaskExecutionAutoConfiguration.class]
ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/cache/CacheAutoConfiguration.class]
ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/cache/GenericCacheConfiguration.class]
ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/cache/SimpleCacheConfiguration.class]
ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/cache/NoOpCacheConfiguration.class]
ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/context/ConfigurationPropertiesAutoConfiguration.class]
ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/info/ProjectInfoAutoConfiguration.class]
ConfigurationClass: beanName 'null', class path resource [org/springframework/boot/autoconfigure/task/TaskSchedulingAutoConfiguration.class]
Первая версия загружает WorkerConfig
перед SomeTestSecondConfiguration
, тогда как вторая версия загружает SomeTestSecondConfiguration
перед WorkerConfig
.
Вы также заметите, что во второй версии есть класс ImportsContextCustomizer$ImportsConfiguration
, который запускает дополнительный импорт.
Если вы посмотрите на SpringBootTestContextBootstrapper
, вы увидите в методе getOrFindConfigurationClasses
, что порядок определен, и ваши дополнительные тестовые классы всегда будут перечислены после основной конфигурации.
tl; dr Если вам нужен определенный порядок, используйте атрибут classes
. Если вы хотите добавить дополнительные компоненты и ничего не пытаетесь переопределить, используйте @Import
.
Вы также можете посмотреть @MockBean
, который предоставляет более надежный способ заменить bean-компонент на макет.
person
Phil Webb
schedule
13.04.2019
@Import
не работает с@TestConfiguration
классами верхнего уровня, хотя в документации указано, что должно. - person ck1   schedule 24.03.2019MyTestsConfiguration
в@Import(MyTestsConfiguration.class)
в разделе 46.3.3 относится к классу, помеченному@TestConfiguration
. - person ck1   schedule 24.03.2019@Import
класса@TestConfiguration
верхнего уровня приводит к определению bean-компонентов в импортированном классе. Не могли бы вы обновить свой вопрос, включив минимальный, полный и поддающийся проверке пример? - person Andy Wilkinson   schedule 27.03.2019