|
|
|
@ -16,7 +16,6 @@ |
|
|
|
|
|
|
|
|
|
|
|
package org.springframework.boot.test.context; |
|
|
|
package org.springframework.boot.test.context; |
|
|
|
|
|
|
|
|
|
|
|
import java.lang.annotation.Annotation; |
|
|
|
|
|
|
|
import java.util.ArrayList; |
|
|
|
import java.util.ArrayList; |
|
|
|
import java.util.Arrays; |
|
|
|
import java.util.Arrays; |
|
|
|
import java.util.Collections; |
|
|
|
import java.util.Collections; |
|
|
|
@ -29,20 +28,16 @@ import java.util.Set; |
|
|
|
import org.springframework.beans.BeanUtils; |
|
|
|
import org.springframework.beans.BeanUtils; |
|
|
|
import org.springframework.boot.SpringApplication; |
|
|
|
import org.springframework.boot.SpringApplication; |
|
|
|
import org.springframework.boot.context.web.ServletContextApplicationContextInitializer; |
|
|
|
import org.springframework.boot.context.web.ServletContextApplicationContextInitializer; |
|
|
|
import org.springframework.boot.test.context.web.WebIntegrationTest; |
|
|
|
|
|
|
|
import org.springframework.boot.test.mock.web.SpringBootMockServletContext; |
|
|
|
import org.springframework.boot.test.mock.web.SpringBootMockServletContext; |
|
|
|
import org.springframework.boot.test.util.EnvironmentTestUtils; |
|
|
|
import org.springframework.boot.test.util.EnvironmentTestUtils; |
|
|
|
import org.springframework.boot.test.web.client.TestRestTemplate; |
|
|
|
|
|
|
|
import org.springframework.context.ApplicationContext; |
|
|
|
import org.springframework.context.ApplicationContext; |
|
|
|
import org.springframework.context.ApplicationContextInitializer; |
|
|
|
import org.springframework.context.ApplicationContextInitializer; |
|
|
|
import org.springframework.context.ConfigurableApplicationContext; |
|
|
|
import org.springframework.context.ConfigurableApplicationContext; |
|
|
|
import org.springframework.core.SpringVersion; |
|
|
|
import org.springframework.core.SpringVersion; |
|
|
|
import org.springframework.core.annotation.AnnotatedElementUtils; |
|
|
|
import org.springframework.core.annotation.AnnotatedElementUtils; |
|
|
|
import org.springframework.core.annotation.AnnotationUtils; |
|
|
|
|
|
|
|
import org.springframework.core.env.ConfigurableEnvironment; |
|
|
|
import org.springframework.core.env.ConfigurableEnvironment; |
|
|
|
import org.springframework.core.env.MapPropertySource; |
|
|
|
import org.springframework.core.env.MapPropertySource; |
|
|
|
import org.springframework.core.env.StandardEnvironment; |
|
|
|
import org.springframework.core.env.StandardEnvironment; |
|
|
|
import org.springframework.mock.web.MockServletContext; |
|
|
|
|
|
|
|
import org.springframework.test.context.ContextConfigurationAttributes; |
|
|
|
import org.springframework.test.context.ContextConfigurationAttributes; |
|
|
|
import org.springframework.test.context.ContextCustomizer; |
|
|
|
import org.springframework.test.context.ContextCustomizer; |
|
|
|
import org.springframework.test.context.ContextLoader; |
|
|
|
import org.springframework.test.context.ContextLoader; |
|
|
|
@ -50,7 +45,6 @@ import org.springframework.test.context.MergedContextConfiguration; |
|
|
|
import org.springframework.test.context.support.AbstractContextLoader; |
|
|
|
import org.springframework.test.context.support.AbstractContextLoader; |
|
|
|
import org.springframework.test.context.support.AnnotationConfigContextLoaderUtils; |
|
|
|
import org.springframework.test.context.support.AnnotationConfigContextLoaderUtils; |
|
|
|
import org.springframework.test.context.support.TestPropertySourceUtils; |
|
|
|
import org.springframework.test.context.support.TestPropertySourceUtils; |
|
|
|
import org.springframework.test.context.web.WebAppConfiguration; |
|
|
|
|
|
|
|
import org.springframework.test.context.web.WebMergedContextConfiguration; |
|
|
|
import org.springframework.test.context.web.WebMergedContextConfiguration; |
|
|
|
import org.springframework.util.Assert; |
|
|
|
import org.springframework.util.Assert; |
|
|
|
import org.springframework.util.ObjectUtils; |
|
|
|
import org.springframework.util.ObjectUtils; |
|
|
|
@ -59,12 +53,22 @@ import org.springframework.web.context.support.GenericWebApplicationContext; |
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* A {@link ContextLoader} that can be used to test Spring Boot applications (those that |
|
|
|
* A {@link ContextLoader} that can be used to test Spring Boot applications (those that |
|
|
|
* normally startup using {@link SpringApplication}). Can be used to test non-web features |
|
|
|
* normally startup using {@link SpringApplication}). Although this loader can be used |
|
|
|
* (like a repository layer) or start an fully-configured embedded servlet container. |
|
|
|
* directly, most test will instead want to use one of the following annotations: |
|
|
|
* <p> |
|
|
|
* <ul> |
|
|
|
* Use {@code @WebIntegrationTest} (or {@code @IntegrationTest} with |
|
|
|
* <li>{@link SpringApplicationTest @SpringApplicationTest} - For non-web applications, or |
|
|
|
* {@code @WebAppConfiguration}) to indicate that you want to use a real servlet container |
|
|
|
* web-applications running under a mock servlet environment</li> |
|
|
|
* or {@code @WebAppConfiguration} alone to use a {@link MockServletContext}. |
|
|
|
* <li>{@link IntegrationTest @IntegrationTest} - To integration test non-web applications |
|
|
|
|
|
|
|
* </li> |
|
|
|
|
|
|
|
* <li> |
|
|
|
|
|
|
|
* {@link org.springframework.boot.test.context.web.WebIntegrationTest @WebIntegrationTest} |
|
|
|
|
|
|
|
* - To integration test web applications (i.e. listening on normal ports).</li> |
|
|
|
|
|
|
|
* </ul> |
|
|
|
|
|
|
|
* The loader supports both standard {@link MergedContextConfiguration} as well as |
|
|
|
|
|
|
|
* {@link WebMergedContextConfiguration}. If {@link WebMergedContextConfiguration} is used |
|
|
|
|
|
|
|
* the context will either use a mock servlet environment, or start the full embedded |
|
|
|
|
|
|
|
* servlet container (depending on the result of {@link #isIntegrationTest |
|
|
|
|
|
|
|
* isIntegrationTest(...)}). |
|
|
|
* <p> |
|
|
|
* <p> |
|
|
|
* If {@code @ActiveProfiles} are provided in the test class they will be used to create |
|
|
|
* If {@code @ActiveProfiles} are provided in the test class they will be used to create |
|
|
|
* the application context. |
|
|
|
* the application context. |
|
|
|
@ -72,16 +76,26 @@ import org.springframework.web.context.support.GenericWebApplicationContext; |
|
|
|
* @author Dave Syer |
|
|
|
* @author Dave Syer |
|
|
|
* @author Phillip Webb |
|
|
|
* @author Phillip Webb |
|
|
|
* @author Andy Wilkinson |
|
|
|
* @author Andy Wilkinson |
|
|
|
|
|
|
|
* @see SpringApplicationTest |
|
|
|
* @see IntegrationTest |
|
|
|
* @see IntegrationTest |
|
|
|
* @see WebIntegrationTest |
|
|
|
* @see org.springframework.boot.test.context.web.WebIntegrationTest |
|
|
|
* @see TestRestTemplate |
|
|
|
|
|
|
|
*/ |
|
|
|
*/ |
|
|
|
public class SpringApplicationContextLoader extends AbstractContextLoader { |
|
|
|
public class SpringApplicationContextLoader extends AbstractContextLoader { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static final Set<String> INTEGRATION_TEST_ANNOTATIONS; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static { |
|
|
|
|
|
|
|
Set<String> annotations = new LinkedHashSet<String>(); |
|
|
|
|
|
|
|
annotations.add("org.springframework.boot.test.context.IntegrationTest"); |
|
|
|
|
|
|
|
annotations.add("org.springframework.boot.test.context.web.WebIntegrationTest"); |
|
|
|
|
|
|
|
annotations.add("org.springframework.boot.test.IntegrationTest"); |
|
|
|
|
|
|
|
annotations.add("org.springframework.boot.test.WebIntegrationTest"); |
|
|
|
|
|
|
|
INTEGRATION_TEST_ANNOTATIONS = Collections.unmodifiableSet(annotations); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public ApplicationContext loadContext(final MergedContextConfiguration config) |
|
|
|
public ApplicationContext loadContext(MergedContextConfiguration config) |
|
|
|
throws Exception { |
|
|
|
throws Exception { |
|
|
|
assertValidAnnotations(config.getTestClass()); |
|
|
|
|
|
|
|
SpringApplication application = getSpringApplication(); |
|
|
|
SpringApplication application = getSpringApplication(); |
|
|
|
application.setMainApplicationClass(config.getTestClass()); |
|
|
|
application.setMainApplicationClass(config.getTestClass()); |
|
|
|
application.setSources(getSources(config)); |
|
|
|
application.setSources(getSources(config)); |
|
|
|
@ -95,7 +109,9 @@ public class SpringApplicationContextLoader extends AbstractContextLoader { |
|
|
|
List<ApplicationContextInitializer<?>> initializers = getInitializers(config, |
|
|
|
List<ApplicationContextInitializer<?>> initializers = getInitializers(config, |
|
|
|
application); |
|
|
|
application); |
|
|
|
if (config instanceof WebMergedContextConfiguration) { |
|
|
|
if (config instanceof WebMergedContextConfiguration) { |
|
|
|
new WebConfigurer().configure(config, application, initializers); |
|
|
|
application.setWebEnvironment(true); |
|
|
|
|
|
|
|
WebConfigurer configurer = new WebConfigurer(isIntegrationTest(config)); |
|
|
|
|
|
|
|
configurer.configure(config, application, initializers); |
|
|
|
} |
|
|
|
} |
|
|
|
else { |
|
|
|
else { |
|
|
|
application.setWebEnvironment(false); |
|
|
|
application.setWebEnvironment(false); |
|
|
|
@ -105,15 +121,6 @@ public class SpringApplicationContextLoader extends AbstractContextLoader { |
|
|
|
return context; |
|
|
|
return context; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private void assertValidAnnotations(Class<?> testClass) { |
|
|
|
|
|
|
|
if (AnnotatedElementUtils.isAnnotated(testClass, WebAppConfiguration.class) |
|
|
|
|
|
|
|
&& AnnotatedElementUtils.isAnnotated(testClass, |
|
|
|
|
|
|
|
WebIntegrationTest.class)) { |
|
|
|
|
|
|
|
throw new IllegalStateException("@WebIntegrationTest and " |
|
|
|
|
|
|
|
+ "@WebAppConfiguration cannot be used together"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Builds new {@link org.springframework.boot.SpringApplication} instance. You can |
|
|
|
* Builds new {@link org.springframework.boot.SpringApplication} instance. You can |
|
|
|
* override this method to add custom behavior |
|
|
|
* override this method to add custom behavior |
|
|
|
@ -147,7 +154,7 @@ public class SpringApplicationContextLoader extends AbstractContextLoader { |
|
|
|
disableJmx(properties); |
|
|
|
disableJmx(properties); |
|
|
|
properties.putAll(TestPropertySourceUtils |
|
|
|
properties.putAll(TestPropertySourceUtils |
|
|
|
.convertInlinedPropertiesToMap(config.getPropertySourceProperties())); |
|
|
|
.convertInlinedPropertiesToMap(config.getPropertySourceProperties())); |
|
|
|
if (!TestAnnotations.isIntegrationTest(config)) { |
|
|
|
if (!isIntegrationTest(config)) { |
|
|
|
properties.putAll(getDefaultEnvironmentProperties()); |
|
|
|
properties.putAll(getDefaultEnvironmentProperties()); |
|
|
|
} |
|
|
|
} |
|
|
|
return properties; |
|
|
|
return properties; |
|
|
|
@ -185,6 +192,21 @@ public class SpringApplicationContextLoader extends AbstractContextLoader { |
|
|
|
return initializers; |
|
|
|
return initializers; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
|
|
|
* Return if the test is a full integration test or not. By default this method checks |
|
|
|
|
|
|
|
* for well known integration test annotations. |
|
|
|
|
|
|
|
* @param config the merged context configuration |
|
|
|
|
|
|
|
* @return if the test is an integration test |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
protected boolean isIntegrationTest(MergedContextConfiguration config) { |
|
|
|
|
|
|
|
for (String annotation : INTEGRATION_TEST_ANNOTATIONS) { |
|
|
|
|
|
|
|
if (AnnotatedElementUtils.isAnnotated(config.getTestClass(), annotation)) { |
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
@Override |
|
|
|
public void processContextConfiguration( |
|
|
|
public void processContextConfiguration( |
|
|
|
ContextConfigurationAttributes configAttributes) { |
|
|
|
ContextConfigurationAttributes configAttributes) { |
|
|
|
@ -233,10 +255,16 @@ public class SpringApplicationContextLoader extends AbstractContextLoader { |
|
|
|
|
|
|
|
|
|
|
|
private static final Class<GenericWebApplicationContext> WEB_CONTEXT_CLASS = GenericWebApplicationContext.class; |
|
|
|
private static final Class<GenericWebApplicationContext> WEB_CONTEXT_CLASS = GenericWebApplicationContext.class; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private final boolean integrationTest; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
WebConfigurer(boolean integrationTest) { |
|
|
|
|
|
|
|
this.integrationTest = integrationTest; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void configure(MergedContextConfiguration configuration, |
|
|
|
void configure(MergedContextConfiguration configuration, |
|
|
|
SpringApplication application, |
|
|
|
SpringApplication application, |
|
|
|
List<ApplicationContextInitializer<?>> initializers) { |
|
|
|
List<ApplicationContextInitializer<?>> initializers) { |
|
|
|
if (!TestAnnotations.isIntegrationTest(configuration)) { |
|
|
|
if (!this.integrationTest) { |
|
|
|
WebMergedContextConfiguration webConfiguration = (WebMergedContextConfiguration) configuration; |
|
|
|
WebMergedContextConfiguration webConfiguration = (WebMergedContextConfiguration) configuration; |
|
|
|
addMockServletContext(initializers, webConfiguration); |
|
|
|
addMockServletContext(initializers, webConfiguration); |
|
|
|
application.setApplicationContextClass(WEB_CONTEXT_CLASS); |
|
|
|
application.setApplicationContextClass(WEB_CONTEXT_CLASS); |
|
|
|
@ -248,8 +276,8 @@ public class SpringApplicationContextLoader extends AbstractContextLoader { |
|
|
|
WebMergedContextConfiguration webConfiguration) { |
|
|
|
WebMergedContextConfiguration webConfiguration) { |
|
|
|
SpringBootMockServletContext servletContext = new SpringBootMockServletContext( |
|
|
|
SpringBootMockServletContext servletContext = new SpringBootMockServletContext( |
|
|
|
webConfiguration.getResourceBasePath()); |
|
|
|
webConfiguration.getResourceBasePath()); |
|
|
|
initializers.add(0, |
|
|
|
initializers.add(0, new ServletContextApplicationContextInitializer( |
|
|
|
new ServletContextApplicationContextInitializer(servletContext)); |
|
|
|
servletContext, true)); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
@ -274,22 +302,6 @@ public class SpringApplicationContextLoader extends AbstractContextLoader { |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static class TestAnnotations { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static boolean isIntegrationTest( |
|
|
|
|
|
|
|
MergedContextConfiguration configuration) { |
|
|
|
|
|
|
|
return (hasAnnotation(configuration, IntegrationTest.class) |
|
|
|
|
|
|
|
|| hasAnnotation(configuration, WebIntegrationTest.class)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private static boolean hasAnnotation(MergedContextConfiguration configuration, |
|
|
|
|
|
|
|
Class<? extends Annotation> annotation) { |
|
|
|
|
|
|
|
return (AnnotationUtils.findAnnotation(configuration.getTestClass(), |
|
|
|
|
|
|
|
annotation) != null); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
/** |
|
|
|
* Adapts a {@link ContextCustomizer} to a {@link ApplicationContextInitializer} so |
|
|
|
* Adapts a {@link ContextCustomizer} to a {@link ApplicationContextInitializer} so |
|
|
|
* that it can be triggered via {@link SpringApplication}. |
|
|
|
* that it can be triggered via {@link SpringApplication}. |
|
|
|
|