Java – context hierarchy in spring boot based testing
My spring boot application starts as follows:
new SpringApplicationBuilder() .sources(ParentCtxConfig.class) .child(ChildFirstCtxConfig.class) .sibling(ChildSecondCtxConfig.class) .run(args);
The configuration class uses the @ springbootapplication annotation Therefore, I have a root context and two sub web contexts
I want to write integration tests where I want the same context hierarchy I want to test the first child context (configured with childfirstctxconfig. Class) with at least its parent context (parentctxconfig. Class) How can I do this?
At present, I have automatically installed ApplicationContext in my test so that I can check it I have this class comment in the test:
@RunWith(SpringRunner.class) @SpringBootTest(classes = { ParentCtxConfig.class,ChildFirstCtxConfig.class },webEnvironment = WebEnvironment.RANDOM_PORT)
But this will produce a single context, and I want a parent - child hierarchy I assume I should annotate my test with the @ contexthierarchy annotation
Change my test comment to, which seems exactly the same as the previous example:
@RunWith(SpringRunner.class) @ContextConfiguration(classes = { ParentCtxConfig.class,ChildFirstCtxConfig.class }) @SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
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)
The context was not started because the bean defined in the parent context could not be found / Auto assembled in the child context Set loader = springbootcontextloader Class doesn't help
Example code: GitHub
Solution
Update: this issue was fixed in spring boot 1.5 mentioned by Peter Davis 0
This is the limit of @ springboottest This is the limitation of spring boot context loader You can solve the problem by configuring the parent context using the custom context loader or working with the contextcustomizer Factories listed in factories The following is a rough example of the latter:
Src / test / resource / meta inf / spring factories:
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()); } } }; } }