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

Aub*_*ine 5 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 {
Run Code Online (Sandbox Code Playgroud)

WorkestTestConfig 的作用是在集成启动期间覆盖真实 bean/一组 bean,每当我使用@ContextConfiguration真实 bean 时,真实 bean 就会退出并使用 WorkerTestConfig 中的 bean,每当我使用真实 bean 时,@Import仍然会创建真实 bean 并导致测试失败。

WorkerTestConfig本身尽可能简单:

@TestConfiguration
public class WorkerTestConfig {

    @Primary
    @Bean
    public ScheduledExecutorService taskExecutor() {
        return DirectExecutorFactory.createSameThreadExecutor();
    }
}
Run Code Online (Sandbox Code Playgroud)

谁能解释一下 @SpringBootTest 注释的另一个神奇行为?如果您重现相同的行为,请确认,以便我可以转到问题跟踪器,因为我已经看到人们在此处 使用@Importwith ,并且在 Spring Boot 文档中没有任何内容禁止它:https: //docs.spring.io/spring-boot/文档/current/reference/html/boot-features-testing.html#boot-features-testing-spring-boot-applications-排除-config@SpringBootTest

完全不知道发生了什么。

版本:2.1.2.RELEASE

更新:

还尝试删除真正的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 {
Run Code Online (Sandbox Code Playgroud)

Phi*_*ebb 7

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

如果您想深入了解并确切了解发生了什么,您可以打开ConfigurationClassParser并在doProcessConfigurationClass. 添加以下条件代码:

System.err.println(configClass);
return false;
Run Code Online (Sandbox Code Playgroud)

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

当您使用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]
Run Code Online (Sandbox Code Playgroud)

当您使用@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]
Run Code Online (Sandbox Code Playgroud)

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

您还会注意到,第二个版本有一个ImportsContextCustomizer$ImportsConfiguration类,它是触发额外导入的类。

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

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

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