Merge branch '2.5.x' into 2.6.x

Closes gh-30664
This commit is contained in:
Andy Wilkinson 2022-04-14 12:40:29 +01:00
commit 887fa4a13f
2 changed files with 64 additions and 6 deletions

View File

@ -62,6 +62,7 @@ import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.web.context.ConfigurableWebApplicationContext;
import org.springframework.web.context.support.GenericWebApplicationContext; import org.springframework.web.context.support.GenericWebApplicationContext;
/** /**
@ -113,14 +114,21 @@ public class SpringBootContextLoader extends AbstractContextLoader {
} }
else if (config instanceof ReactiveWebMergedContextConfiguration) { else if (config instanceof ReactiveWebMergedContextConfiguration) {
application.setWebApplicationType(WebApplicationType.REACTIVE); application.setWebApplicationType(WebApplicationType.REACTIVE);
if (!isEmbeddedWebEnvironment(config)) {
application.setApplicationContextFactory(
ApplicationContextFactory.of(GenericReactiveWebApplicationContext::new));
}
} }
else { else {
application.setWebApplicationType(WebApplicationType.NONE); application.setWebApplicationType(WebApplicationType.NONE);
} }
application.setApplicationContextFactory((type) -> {
if (type != WebApplicationType.NONE && !isEmbeddedWebEnvironment(config)) {
if (type == WebApplicationType.REACTIVE) {
return new GenericReactiveWebApplicationContext();
}
else if (type == WebApplicationType.SERVLET) {
return new GenericWebApplicationContext();
}
}
return ApplicationContextFactory.DEFAULT.create(type);
});
application.setInitializers(initializers); application.setInitializers(initializers);
boolean customEnvironent = ReflectionUtils.findMethod(getClass(), "getEnvironment") boolean customEnvironent = ReflectionUtils.findMethod(getClass(), "getEnvironment")
.getDeclaringClass() != SpringBootContextLoader.class; .getDeclaringClass() != SpringBootContextLoader.class;
@ -285,14 +293,38 @@ public class SpringBootContextLoader extends AbstractContextLoader {
List<ApplicationContextInitializer<?>> initializers) { List<ApplicationContextInitializer<?>> initializers) {
WebMergedContextConfiguration webConfiguration = (WebMergedContextConfiguration) configuration; WebMergedContextConfiguration webConfiguration = (WebMergedContextConfiguration) configuration;
addMockServletContext(initializers, webConfiguration); addMockServletContext(initializers, webConfiguration);
application.setApplicationContextFactory((webApplicationType) -> new GenericWebApplicationContext());
} }
private void addMockServletContext(List<ApplicationContextInitializer<?>> initializers, private void addMockServletContext(List<ApplicationContextInitializer<?>> initializers,
WebMergedContextConfiguration webConfiguration) { WebMergedContextConfiguration webConfiguration) {
SpringBootMockServletContext servletContext = new SpringBootMockServletContext( SpringBootMockServletContext servletContext = new SpringBootMockServletContext(
webConfiguration.getResourceBasePath()); webConfiguration.getResourceBasePath());
initializers.add(0, new ServletContextApplicationContextInitializer(servletContext, true)); initializers.add(0, new DefensiveWebApplicationContextInitializer(
new ServletContextApplicationContextInitializer(servletContext, true)));
}
/**
* Decorator for {@link ServletContextApplicationContextInitializer} that prevents
* a failure when the context type is not as was predicted when the initializer
* was registered. This can occur when spring.main.web-application-type is set to
* something other than servlet.
*/
private static final class DefensiveWebApplicationContextInitializer
implements ApplicationContextInitializer<ConfigurableApplicationContext> {
private final ServletContextApplicationContextInitializer delegate;
private DefensiveWebApplicationContextInitializer(ServletContextApplicationContextInitializer delegate) {
this.delegate = delegate;
}
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
if (applicationContext instanceof ConfigurableWebApplicationContext) {
this.delegate.initialize((ConfigurableWebApplicationContext) applicationContext);
}
}
} }
} }

View File

@ -24,6 +24,7 @@ import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.boot.web.reactive.context.GenericReactiveWebApplicationContext;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.ConfigurableEnvironment;
@ -36,6 +37,7 @@ import org.springframework.test.context.TestContextManager;
import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.support.TestPropertySourceUtils; import org.springframework.test.context.support.TestPropertySourceUtils;
import org.springframework.test.util.ReflectionTestUtils; import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.web.context.WebApplicationContext;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -146,6 +148,20 @@ class SpringBootContextLoaderTests {
assertThat(last).startsWith("Config resource"); assertThat(last).startsWith("Config resource");
} }
@Test
void whenEnvironmentChangesWebApplicationTypeToNoneThenContextTypeChangesAccordingly() {
TestContext context = new ExposedTestContextManager(ChangingWebApplicationTypeToNone.class)
.getExposedTestContext();
assertThat(context.getApplicationContext()).isNotInstanceOf(WebApplicationContext.class);
}
@Test
void whenEnvironmentChangesWebApplicationTypeToReactiveThenContextTypeChangesAccordingly() {
TestContext context = new ExposedTestContextManager(ChangingWebApplicationTypeToReactive.class)
.getExposedTestContext();
assertThat(context.getApplicationContext()).isInstanceOf(GenericReactiveWebApplicationContext.class);
}
private String[] getActiveProfiles(Class<?> testClass) { private String[] getActiveProfiles(Class<?> testClass) {
TestContext testContext = new ExposedTestContextManager(testClass).getExposedTestContext(); TestContext testContext = new ExposedTestContextManager(testClass).getExposedTestContext();
ApplicationContext applicationContext = testContext.getApplicationContext(); ApplicationContext applicationContext = testContext.getApplicationContext();
@ -228,6 +244,16 @@ class SpringBootContextLoaderTests {
} }
@SpringBootTest(classes = Config.class, args = "--spring.main.web-application-type=none")
static class ChangingWebApplicationTypeToNone {
}
@SpringBootTest(classes = Config.class, args = "--spring.main.web-application-type=reactive")
static class ChangingWebApplicationTypeToReactive {
}
/** /**
* {@link TestContextManager} which exposes the {@link TestContext}. * {@link TestContextManager} which exposes the {@link TestContext}.
*/ */