Spring 基于引导的测试中的上下文层次结构
Context hierarchy in Spring Boot based tests
我的Spring启动应用程序是这样启动的:
new SpringApplicationBuilder()
.sources(ParentCtxConfig.class)
.child(ChildFirstCtxConfig.class)
.sibling(ChildSecondCtxConfig.class)
.run(args);
Config classes 用 @SpringBootApplication
注释。结果,我有一个根上下文和两个子 Web 上下文。
我想编写集成测试,我希望那里有相同的上下文层次结构。我至少要用他的父上下文 (ParentCtxConfig.class
) 测试第一个子上下文(配置 ChildFirstCtxConfig.class
)。我怎样才能做到这一点?
目前我在测试中自动连接了 ApplicationContext
以便我可以检查它。我在测试中有这个 class 注释:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { ParentCtxConfig.class, ChildFirstCtxConfig.class }, webEnvironment = WebEnvironment.RANDOM_PORT)
但这会产生单一上下文,我想要父子层次结构。
我假设我应该用 @ContextHierarchy
注释来注释我的测试。
将我的测试注释更改为此似乎与前面的示例完全相同:
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = { ParentCtxConfig.class, ChildFirstCtxConfig.class })
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
但是如果我要介绍@ContextHierarchy
并且有这样的东西:
@RunWith(SpringRunner.class)
@ContextHierarchy({
@ContextConfiguration(name = "root", classes = ParentCtxConfig.class),
@ContextConfiguration(name = "child", classes = ChildFirstCtxConfig.class)
})
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
上下文未启动,因为在父上下文中定义的 bean 不能在子上下文中 found/autowired。设置 loader = SpringBootContextLoader.class
没有帮助。
示例代码:GitHub
更新: This issue was fixed in Spring Boot 1.5.0 如彼得·戴维斯所述。
这是 @SpringBootTest
的限制。准确移动,是SpringBootContextLoader
的限制。您可以通过使用配置父上下文的自定义上下文加载器或使用 ContextCustomizer
需要在 spring.factories
中列出的工厂来解决它。这是后者的粗略示例:
src/test/resources/META-INF/spring.工厂:
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启动应用程序是这样启动的:
new SpringApplicationBuilder()
.sources(ParentCtxConfig.class)
.child(ChildFirstCtxConfig.class)
.sibling(ChildSecondCtxConfig.class)
.run(args);
Config classes 用 @SpringBootApplication
注释。结果,我有一个根上下文和两个子 Web 上下文。
我想编写集成测试,我希望那里有相同的上下文层次结构。我至少要用他的父上下文 (ParentCtxConfig.class
) 测试第一个子上下文(配置 ChildFirstCtxConfig.class
)。我怎样才能做到这一点?
目前我在测试中自动连接了 ApplicationContext
以便我可以检查它。我在测试中有这个 class 注释:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = { ParentCtxConfig.class, ChildFirstCtxConfig.class }, webEnvironment = WebEnvironment.RANDOM_PORT)
但这会产生单一上下文,我想要父子层次结构。
我假设我应该用 @ContextHierarchy
注释来注释我的测试。
将我的测试注释更改为此似乎与前面的示例完全相同:
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = { ParentCtxConfig.class, ChildFirstCtxConfig.class })
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
但是如果我要介绍@ContextHierarchy
并且有这样的东西:
@RunWith(SpringRunner.class)
@ContextHierarchy({
@ContextConfiguration(name = "root", classes = ParentCtxConfig.class),
@ContextConfiguration(name = "child", classes = ChildFirstCtxConfig.class)
})
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
上下文未启动,因为在父上下文中定义的 bean 不能在子上下文中 found/autowired。设置 loader = SpringBootContextLoader.class
没有帮助。
示例代码:GitHub
更新: This issue was fixed in Spring Boot 1.5.0 如彼得·戴维斯所述。
这是 @SpringBootTest
的限制。准确移动,是SpringBootContextLoader
的限制。您可以通过使用配置父上下文的自定义上下文加载器或使用 ContextCustomizer
需要在 spring.factories
中列出的工厂来解决它。这是后者的粗略示例:
src/test/resources/META-INF/spring.工厂:
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());
}
}
};
}
}