Context Hierarchy in Spring Load Based Tests

My Spring boot application starts as follows:

new SpringApplicationBuilder() .sources(ParentCtxConfig.class) .child(ChildFirstCtxConfig.class) .sibling(ChildSecondCtxConfig.class) .run(args); 

Configuration classes are annotated using @SpringBootApplication . As a result, I have one root context and two child web contexts.

I want to write an integration test, and I would like to have the same hierarchy of contexts. I want to at least test the first child context (configured with ChildFirstCtxConfig.class ) with its parent context ( ParentCtxConfig.class ). How can i achieve this?

I have currently outsourced ApplicationContext in my test to test it. I have an annotation for this class in a test:

 @RunWith(SpringRunner.class) @SpringBootTest(classes = { ParentCtxConfig.class, ChildFirstCtxConfig.class }, webEnvironment = WebEnvironment.RANDOM_PORT) 

but this will create a single context, and I want a parent-child hierarchy. I suggest that I should annotate my test with the @ContextHierarchy annotation.

Changing my test annotation to this seems to work exactly the same as in 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 does not start due to the bean defined in the parent context, cannot be found / auto-notified in the context of the child. Setting loader = SpringBootContextLoader.class does not help.

Sample Code: GitHub

+6
source share
1 answer

Update: This issue has been fixed in Spring Boot 1.5.0 , as Peter Davis mentioned.

This is a limitation of @SpringBootTest . Go for sure, this is a limitation of SpringBootContextLoader . You can get around this using a custom context loader that sets up the parent context or ContextCustomizer factory, which will need to be specified in spring.factories . Here is a rough example of the latter:

SRC / test / resources / 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()); } } }; } } 
+5
source

Source: https://habr.com/ru/post/1014145/


All Articles