对于@TestConfiguration类@SpringBootTest @Import不执行任何操作,而@Contex



考虑以下集成测试注释:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE,
properties = "spring.main.allow-bean-definition-overriding=true")
@ContextConfiguration(classes = {WorkerTestConfig.class})
//@Import(value = {WorkerTestConfig.class})
@ActiveProfiles({"dev","test"})
public class NumberServiceITest {

WorkestTestConfig 的作用是在集成启动期间覆盖真正的 bean/abe 集,每当我使用@ContextConfiguration真正的 bean 正在退出并使用 WorkerTestConfig 中的 bean,每当我使用@Import真正的 bean 仍然被创建并且测试失败

WorkerTestConfig本身尽可能琐碎:

@TestConfiguration
public class WorkerTestConfig {
@Primary
@Bean
public ScheduledExecutorService taskExecutor() {
return DirectExecutorFactory.createSameThreadExecutor();
}
}

谁能解释一下@SpringBootTest注释的另一种神奇行为?如果您重现相同的行为,请确认,以便我可以转到问题跟踪器,因为我看到人们在 SO 上使用带有@SpringBootTest@Import,并且在 Spring 启动文档中没有任何禁止它: https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html#boot-features-testing-spring-boot-applications-excluding-config

完全不明白发生了什么。

版本: 2.1.2.发布

更新:

还尝试删除真正的 bean,看看问题是否只是覆盖,但@Import注释只是死在水中,不起作用 ->甚至无法创建 bean,@ContextConfiguration具有添加/覆盖行为,导入什么都不做。 批注的完全限定导入为: import org.springframework.context.annotation.Import;

还试图从@TestConfiguration改为@Configuration只是为了它,什么都没有。死。

更新 2:

@Import适用于标准弹簧测试:

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {Some.class,
Some2WhichDependsOnWorkerTestConfig.class})
@Import(WorkerTestConfig.class)
@ActiveProfiles("test")
public class SomeOtherTest {

未定义在测试中使用@Import类时处理它们的顺序。添加测试的@Import功能主要是为了允许轻松注册其他bean,无意使用它来替换bean 定义。

如果你想挖掘杂草并确切地看到发生了什么,你可以打开ConfigurationClassParser并在doProcessConfigurationClass中添加条件断点。添加以下条件代码:

System.err.println(configClass);
return false;

现在,如果您调试应用程序,您将在处理配置类时获得额外的输出。

当您使用不带@Importclasses注释属性时,您将看到:

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]

当您使用不带classes属性的@Import时,您将获得:

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]

第一个版本在SomeTestSecondConfiguration之前加载WorkerConfig,而第二个版本在WorkerConfig之前加载SomeTestSecondConfiguration

您还会注意到第二个版本有一个ImportsContextCustomizer$ImportsConfiguration类,这是触发其他导入的东西。

如果您查看SpringBootTestContextBootstrapper您可以在getOrFindConfigurationClasses方法中看到定义了排序,并且您的其他测试类将始终列在主配置之后。

tl;dr 如果需要定义的排序,请使用classes属性。如果您想添加其他 bean 并且您没有尝试覆盖任何内容,请使用@Import.

您可能还想看看@MockBean它提供了一种更强大的方法来用模拟替换 bean。

最新更新