基于Spring Boot的测试中的上下文层次结构 [英] Context hierarchy in Spring Boot based tests
问题描述
我的Spring Boot应用程序是这样启动的:
My Spring Boot application is started like this:
new SpringApplicationBuilder()
.sources(ParentCtxConfig.class)
.child(ChildFirstCtxConfig.class)
.sibling(ChildSecondCtxConfig.class)
.run(args);
Config类用@SpringBootApplication
注释.结果,我有一个根上下文和两个子Web上下文.
Config classes are annotated with @SpringBootApplication
. As a result, I have one root context and two child web contexts.
我想编写集成测试,并且我希望在那里具有相同的上下文层次结构.我至少要使用其父级上下文(ParentCtxConfig.class
)测试第一个子级上下文(用ChildFirstCtxConfig.class
配置).我该如何实现?
I want to write integration test and I would like to have same context hierarchy there. I want at least to test first child context (configured with ChildFirstCtxConfig.class
) with his parent context (ParentCtxConfig.class
). How can I achieve that?
当前,我在测试中为ApplicationContext
自动接线,以便对其进行检查.我在测试中有此类注释:
Currently I autowired ApplicationContext
in my test so I can inspect it. I have this class annotation in the test:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { ParentCtxConfig.class, ChildFirstCtxConfig.class }, webEnvironment = WebEnvironment.RANDOM_PORT)
但是会产生单个上下文,我想要父子层次结构.
我假设我应该使用@ContextHierarchy
批注对测试进行批注.
but that will produce single context and I want parent-child hierarchy.
I assume that I should annotate my test with @ContextHierarchy
annotation.
将我的测试注释更改为此似乎与之前的示例完全相同:
Changing my test annotation to this seems to work exactly the same like previous example:
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = { ParentCtxConfig.class, ChildFirstCtxConfig.class })
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
但是,如果我想介绍@ContextHierarchy
,并且有这样的内容:
But if I want to introduce @ContextHierarchy
and have something like this:
@RunWith(SpringRunner.class)
@ContextHierarchy({
@ContextConfiguration(name = "root", classes = ParentCtxConfig.class),
@ContextConfiguration(name = "child", classes = ChildFirstCtxConfig.class)
})
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
上下文未启动,因为无法在子上下文中找到/自动装配在父上下文中定义的bean.设置loader = SpringBootContextLoader.class
没有帮助.
context is not started because of bean defined in parent context can't be found/autowired in child context. Setting loader = SpringBootContextLoader.class
doesn't help.
示例代码: GitHub >
推荐答案
This is a limitation of @SpringBootTest
. Move accurately, it's a limitation of SpringBootContextLoader
. You could work around it by using a custom context loader that configures the parent context or with a ContextCustomizer
the factory for which would need to be listed in spring.factories
. Here's a rough example of the latter:
org.springframework.test.context.ContextCustomizerFactory=\
com.alex.demo.ctx.HierarchyContextCustomizerFactory
src/test/java/com/alex/demo/ctx/HierarchyContextCustomizerFactory.java:
package com.alex.demo.ctx;
import java.util.List;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.test.context.ContextConfigurationAttributes;
import org.springframework.test.context.ContextCustomizer;
import org.springframework.test.context.ContextCustomizerFactory;
import org.springframework.test.context.MergedContextConfiguration;
public class HierarchyContextCustomizerFactory implements ContextCustomizerFactory {
@Override
public ContextCustomizer createContextCustomizer(Class<?> testClass,
List<ContextConfigurationAttributes> configAttributes) {
return new ContextCustomizer() {
@Override
public void customizeContext(ConfigurableApplicationContext context,
MergedContextConfiguration mergedConfig) {
if (mergedConfig.getParentApplicationContext() != null) {
context.setParent(mergedConfig.getParentApplicationContext());
}
}
};
}
}
这篇关于基于Spring Boot的测试中的上下文层次结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!