Skip to content

Commit

Permalink
Provide a way to create custom ApplicationContextFactory
Browse files Browse the repository at this point in the history
Update `SpringBootContextLoader` so that `getApplicationContextFactory`
is now a protected that may be overridden to provide a custom
`ApplicationContextFactory` instance.

Closes spring-projectsgh-38205
  • Loading branch information
philwebb committed Nov 7, 2023
1 parent f22c1ba commit 690cfa2
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,7 @@ else if (mergedConfig instanceof ReactiveWebMergedContextConfiguration) {
else {
application.setWebApplicationType(WebApplicationType.NONE);
}
application.setApplicationContextFactory(
(webApplicationType) -> getApplicationContextFactory(mergedConfig, webApplicationType));
application.setApplicationContextFactory(getApplicationContextFactory(mergedConfig));
if (mergedConfig.getParent() != null) {
application.setBannerMode(Banner.Mode.OFF);
}
Expand All @@ -212,17 +211,26 @@ else if (mergedConfig instanceof ReactiveWebMergedContextConfiguration) {
}
}

private ConfigurableApplicationContext getApplicationContextFactory(MergedContextConfiguration mergedConfig,
WebApplicationType webApplicationType) {
if (webApplicationType != WebApplicationType.NONE && !isEmbeddedWebEnvironment(mergedConfig)) {
if (webApplicationType == WebApplicationType.REACTIVE) {
return new GenericReactiveWebApplicationContext();
}
if (webApplicationType == WebApplicationType.SERVLET) {
return new GenericWebApplicationContext();
/**
* Return the {@link ApplicationContextFactory} that should be used for the test. By
* default this method will return a factory that will create an appropriate
* {@link ApplicationContext} for the {@link WebApplicationType}.
* @param mergedConfig the merged context configuration
* @return the application context factory to use
* @since 3.2.0
*/
protected ApplicationContextFactory getApplicationContextFactory(MergedContextConfiguration mergedConfig) {
return (webApplicationType) -> {
if (webApplicationType != WebApplicationType.NONE && !isEmbeddedWebEnvironment(mergedConfig)) {
if (webApplicationType == WebApplicationType.REACTIVE) {
return new GenericReactiveWebApplicationContext();
}
if (webApplicationType == WebApplicationType.SERVLET) {
return new GenericWebApplicationContext();
}
}
}
return ApplicationContextFactory.DEFAULT.create(webApplicationType);
return ApplicationContextFactory.DEFAULT.create(webApplicationType);
};
}

private void prepareEnvironment(MergedContextConfiguration mergedConfig, SpringApplication application,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,14 @@
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.BeanCreationException;
import org.springframework.boot.ApplicationContextFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.boot.test.context.SpringBootTest.UseMainMethod;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.boot.web.reactive.context.GenericReactiveWebApplicationContext;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment;
Expand Down Expand Up @@ -246,6 +248,13 @@ void whenUseMainMethodWithContextHierarchyThrowsException() {
.withMessage("UseMainMethod.ALWAYS cannot be used with @ContextHierarchy tests");
}

@Test
void whenSubclassProvidesCustomApplicationContextFactory() {
TestContext testContext = new ExposedTestContextManager(CustomApplicationContextTest.class)
.getExposedTestContext();
assertThat(testContext.getApplicationContext()).isInstanceOf(CustomAnnotationConfigApplicationContext.class);
}

private String[] getActiveProfiles(Class<?> testClass) {
TestContext testContext = new ExposedTestContextManager(testClass).getExposedTestContext();
ApplicationContext applicationContext = testContext.getApplicationContext();
Expand Down Expand Up @@ -370,6 +379,25 @@ static class UseMainMethodWithContextHierarchy {

}

@SpringBootTest
@ContextConfiguration(classes = Config.class, loader = CustomApplicationContextSpringBootContextLoader.class)
static class CustomApplicationContextTest {

}

static class CustomApplicationContextSpringBootContextLoader extends SpringBootContextLoader {

@Override
protected ApplicationContextFactory getApplicationContextFactory(MergedContextConfiguration mergedConfig) {
return (webApplicationType) -> new CustomAnnotationConfigApplicationContext();
}

}

static class CustomAnnotationConfigApplicationContext extends AnnotationConfigApplicationContext {

}

@Configuration(proxyBeanMethods = false)
static class Config {

Expand Down

0 comments on commit 690cfa2

Please sign in to comment.