Throw ContextLoadException on test context load failure

When a test context fails to load, a `ContextLoadException` should
be thrown so that Framework can catch it and call any registered
`ApplicationContextFailureProcessor`s.

Closes gh-31793
This commit is contained in:
Scott Frederick
2022-11-08 16:46:09 -06:00
parent 70f7258341
commit b882de7c68
3 changed files with 128 additions and 14 deletions

View File

@@ -21,20 +21,24 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.BeanCreationException;
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.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.PropertySource;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.ApplicationContextFailureProcessor;
import org.springframework.test.context.MergedContextConfiguration;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.TestContextManager;
@@ -55,6 +59,11 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
*/
class SpringBootContextLoaderTests {
@BeforeEach
void setUp() {
ContextLoaderApplicationContextFailureProcessor.reset();
}
@Test
void environmentPropertiesSimple() {
Map<String, Object> config = getMergedContextConfigurationProperties(SimpleConfig.class);
@@ -197,6 +206,32 @@ class SpringBootContextLoaderTests {
assertThat(applicationContext.getEnvironment().getActiveProfiles()).isEmpty();
}
@Test
void whenUseMainMethodWithBeanThrowingException() {
TestContext testContext = new ExposedTestContextManager(UseMainMethodWithBeanThrowingException.class)
.getExposedTestContext();
assertThatIllegalStateException().isThrownBy(testContext::getApplicationContext).havingCause()
.satisfies((exception) -> {
assertThat(exception).isInstanceOf(BeanCreationException.class);
assertThat(exception)
.isSameAs(ContextLoaderApplicationContextFailureProcessor.contextLoadException);
});
assertThat(ContextLoaderApplicationContextFailureProcessor.failedContext).isNotNull();
}
@Test
void whenNoMainMethodWithBeanThrowingException() {
TestContext testContext = new ExposedTestContextManager(NoMainMethodWithBeanThrowingException.class)
.getExposedTestContext();
assertThatIllegalStateException().isThrownBy(testContext::getApplicationContext).havingCause()
.satisfies((exception) -> {
assertThat(exception).isInstanceOf(BeanCreationException.class);
assertThat(exception)
.isSameAs(ContextLoaderApplicationContextFailureProcessor.contextLoadException);
});
assertThat(ContextLoaderApplicationContextFailureProcessor.failedContext).isNotNull();
}
private String[] getActiveProfiles(Class<?> testClass) {
TestContext testContext = new ExposedTestContextManager(testClass).getExposedTestContext();
ApplicationContext applicationContext = testContext.getApplicationContext();
@@ -284,7 +319,7 @@ class SpringBootContextLoaderTests {
}
@SpringBootTest(classes = ConfigWithThrowingMain.class, useMainMethod = UseMainMethod.ALWAYS)
@SpringBootTest(classes = ConfigWithMainThrowingException.class, useMainMethod = UseMainMethod.ALWAYS)
static class UseMainMethodAlwaysAndMainMethodThrowsException {
}
@@ -304,6 +339,16 @@ class SpringBootContextLoaderTests {
}
@SpringBootTest(classes = ConfigWithMainWithBeanThrowingException.class, useMainMethod = UseMainMethod.ALWAYS)
static class UseMainMethodWithBeanThrowingException {
}
@SpringBootTest(classes = ConfigWithNoMainWithBeanThrowingException.class, useMainMethod = UseMainMethod.NEVER)
static class NoMainMethodWithBeanThrowingException {
}
@Configuration(proxyBeanMethods = false)
static class Config {
@@ -327,7 +372,33 @@ class SpringBootContextLoaderTests {
@Configuration(proxyBeanMethods = false)
@SpringBootConfiguration
public static class ConfigWithThrowingMain {
public static class ConfigWithMainWithBeanThrowingException {
public static void main(String[] args) {
new SpringApplication(ConfigWithMainWithBeanThrowingException.class).run();
}
@Bean
String failContextLoad() {
throw new RuntimeException("ThrownFromBeanMethod");
}
}
@Configuration(proxyBeanMethods = false)
@SpringBootConfiguration
static class ConfigWithNoMainWithBeanThrowingException {
@Bean
String failContextLoad() {
throw new RuntimeException("ThrownFromBeanMethod");
}
}
@Configuration(proxyBeanMethods = false)
@SpringBootConfiguration
public static class ConfigWithMainThrowingException {
public static void main(String[] args) {
throw new RuntimeException("ThrownFromMain");
@@ -350,4 +421,23 @@ class SpringBootContextLoaderTests {
}
private static class ContextLoaderApplicationContextFailureProcessor implements ApplicationContextFailureProcessor {
static ApplicationContext failedContext;
static Throwable contextLoadException;
@Override
public void processLoadFailure(ApplicationContext context, Throwable exception) {
failedContext = context;
contextLoadException = exception;
}
private static void reset() {
failedContext = null;
contextLoadException = null;
}
}
}

View File

@@ -1,2 +1,5 @@
org.springframework.boot.test.context.DefaultTestExecutionListenersPostProcessor=\
org.springframework.boot.test.context.bootstrap.TestDefaultTestExecutionListenersPostProcessor
org.springframework.test.context.ApplicationContextFailureProcessor=\
org.springframework.boot.test.context.SpringBootContextLoaderTests.ContextLoaderApplicationContextFailureProcessor