自定义注解中的@ContextConfiguration可以合并吗?

Grz*_*ski 1 spring-test spring-boot

我正在研究自定义 Spring Boot 启动器。在测试启动器中,我想要做的是实现一个组合注释,它将@Configuration向 中添加其他类ApplicationContext(并且可能在 中使用此注释TestExecutionListener)。前任:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@ContextConfiguration(classes = AdditionalTestConfiguration.class)
public @interface ComposedAnnotation {
}
Run Code Online (Sandbox Code Playgroud)

并在我的 Spring Boot 集成测试中使用它:

@RunWith(SpringJUnit4ClassRunner.class)
@WebIntegrationTest
@SpringApplicationConfiguration(Application.class)
@ComposedAnnotation
public class SomeTest {
}
Run Code Online (Sandbox Code Playgroud)

不涉及继承。不幸的是,它似乎不起作用。我怀疑这是 Spring Boot 的问题,而不是 Spring 测试框架本身。

有什么办法可以达到预期的效果吗?

Sam*_*nen 5

你是对的:这不是 Spring Boot 的问题。但这也不是问题spring-test

相反,这是 Spring 的一般预期行为。有关详细信息,请查看我对此问题的回答:元注释中的 @ActiveProfiles 和测试类不起作用

总之,您无法通过@ContextConfiguration在单个测试类上声明两个注释(直接或作为元注释)来实现此目的。

然而,我刚刚想出了一个技巧,可以让你实现这一目标。具体来说,您可以创建一个ApplicationContextInitializer注册一个或多个@Configuration类的 (ACI)。在您的组合注释中,您可以注册此 ACI 以注册始终存在的@Configuration。当实际使用组合注释时,它可以@Configuration像平常一样声明额外的类。

我刚刚在此提交中提交了一个工作示例。

基本上,代码看起来像这样:

@ContextConfiguration(loader = AnnotationConfigContextLoader.class, initializers = FooConfigInitializer.class)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComposedContextConfiguration {

    @AliasFor(annotation = ContextConfiguration.class, attribute = "classes")
    Class<?>[] value() default {};
}
Run Code Online (Sandbox Code Playgroud)
public class FooConfigInitializer implements ApplicationContextInitializer<GenericApplicationContext> {

    @Override
    public void initialize(GenericApplicationContext applicationContext) {
        new AnnotatedBeanDefinitionReader(applicationContext).register(FooConfig.class);
    }
}
Run Code Online (Sandbox Code Playgroud)

你可以这样使用它:

@RunWith(SpringRunner.class)
@ComposedContextConfiguration(BarConfig.class)
public class InitializerConfiguredViaMetaAnnotationTests { /* ... */ }
Run Code Online (Sandbox Code Playgroud)

然后您的ApplicationContext遗嘱将从FooConfig和加载BarConfig

上面的例子显然没有使用Spring Boot,但是同样的原理应该也适用于@SpringApplicationConfiguration.

问候,

Sam(Spring TestContext 框架的作者