对于@SpringBootTest @TestConfiguration类的@Import不执行任何操作,而@ContextConfiguration会按预期覆盖

时间:2019-03-24 17:26:00

标签: spring-boot spring-boot-test

考虑以下集成测试注释:

@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 /一组bean,每当我使用@ContextConfiguration时,真实的bean就退后,并且使用WorkerTestConfig的bean,每当我使用{{1} }真正的bean仍在创建,并且未通过测试。

@Import本身尽可能琐碎:

WorkerTestConfig

有人可以解释@SpringBootTest批注的另一种神奇行为吗?如果您重现相同的行为,请确认,以便进入问题跟踪程序,因为我看到人们在此处在SO @TestConfiguration public class WorkerTestConfig { @Primary @Bean public ScheduledExecutorService taskExecutor() { return DirectExecutorFactory.createSameThreadExecutor(); } } @Import上使用@SpringBootTest,并且在spring boot docs中没有禁止它的内容: 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具有添加剂/覆盖行为,导入根本不执行任何操作。 注释的完全合格导入为: 导入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 {

1 个答案:

答案 0 :(得分:1)

未定义@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属性。如果要添加其他bean,并且您不想覆盖任何内容,请使用@Import

您可能还想看看@MockBean,它提供了一种更健壮的方法来用模拟代替bean。