diff --git a/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootTestContextBootstrapper.java b/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootTestContextBootstrapper.java index 31c5c2fd577..15daa0c9e83 100644 --- a/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootTestContextBootstrapper.java +++ b/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootTestContextBootstrapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2016 the original author or authors. + * Copyright 2012-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,6 +19,7 @@ package org.springframework.boot.test.context; import java.lang.annotation.Annotation; import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; import java.util.List; import java.util.Set; @@ -28,9 +29,12 @@ import org.apache.commons.logging.LogFactory; import org.springframework.boot.SpringBootConfiguration; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.core.annotation.AnnotatedElementUtils; +import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.env.Environment; import org.springframework.core.io.support.SpringFactoriesLoader; +import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfigurationAttributes; +import org.springframework.test.context.ContextHierarchy; import org.springframework.test.context.ContextLoader; import org.springframework.test.context.MergedContextConfiguration; import org.springframework.test.context.TestContext; @@ -137,7 +141,7 @@ public class SpringBootTestContextBootstrapper extends DefaultTestContextBootstr propertySourceProperties .toArray(new String[propertySourceProperties.size()])); WebEnvironment webEnvironment = getWebEnvironment(mergedConfig.getTestClass()); - if (webEnvironment != null) { + if (webEnvironment != null && isWebEnvironmentSupported(mergedConfig)) { if (webEnvironment.isEmbedded() || (webEnvironment == WebEnvironment.MOCK && hasWebEnvironmentClasses())) { WebAppConfiguration webAppConfiguration = AnnotatedElementUtils @@ -152,6 +156,32 @@ public class SpringBootTestContextBootstrapper extends DefaultTestContextBootstr return mergedConfig; } + private boolean isWebEnvironmentSupported(MergedContextConfiguration mergedConfig) { + Class testClass = mergedConfig.getTestClass(); + ContextHierarchy hierarchy = AnnotationUtils.getAnnotation(testClass, + ContextHierarchy.class); + if (hierarchy == null || hierarchy.value().length == 0) { + return true; + } + ContextConfiguration[] configurations = hierarchy.value(); + return isFromConfiguration(mergedConfig, + configurations[configurations.length - 1]); + } + + private boolean isFromConfiguration(MergedContextConfiguration candidateConfig, + ContextConfiguration configuration) { + ContextConfigurationAttributes attributes = new ContextConfigurationAttributes( + candidateConfig.getTestClass(), configuration); + Set> configurationClasses = new HashSet>( + Arrays.asList(attributes.getClasses())); + for (Class candidate : candidateConfig.getClasses()) { + if (configurationClasses.contains(candidate)) { + return true; + } + } + return false; + } + private boolean hasWebEnvironmentClasses() { for (String className : WEB_ENVIRONMENT_CLASSES) { if (!ClassUtils.isPresent(className, null)) { diff --git a/spring-boot-test/src/test/java/org/springframework/boot/test/context/SpringBootTestWebEnvironmentContextHierarchyTests.java b/spring-boot-test/src/test/java/org/springframework/boot/test/context/SpringBootTestWebEnvironmentContextHierarchyTests.java new file mode 100644 index 00000000000..e506577a662 --- /dev/null +++ b/spring-boot-test/src/test/java/org/springframework/boot/test/context/SpringBootTestWebEnvironmentContextHierarchyTests.java @@ -0,0 +1,75 @@ +/* + * Copyright 2012-2017 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test.context; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.AbstractSpringBootTestEmbeddedWebEnvironmentTests.AbstractConfig; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.test.context.SpringBootTestWebEnvironmentContextHierarchyTests.ChildConfiguration; +import org.springframework.boot.test.context.SpringBootTestWebEnvironmentContextHierarchyTests.ParentConfiguration; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.ContextHierarchy; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.context.WebApplicationContext; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link SpringBootTest} configured with {@link WebEnvironment#DEFINED_PORT}. + * + * @author Phillip Webb + * @author Andy Wilkinson + */ +@RunWith(SpringRunner.class) +@DirtiesContext +@SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT, properties = { + "server.port=0", "value=123" }) +@ContextHierarchy({ @ContextConfiguration(classes = ParentConfiguration.class), + @ContextConfiguration(classes = ChildConfiguration.class) }) +public class SpringBootTestWebEnvironmentContextHierarchyTests { + + @Autowired + private ApplicationContext context; + + @Test + public void testShouldOnlyStartSingleServer() throws Exception { + ApplicationContext parent = this.context.getParent(); + assertThat(this.context).isInstanceOf(WebApplicationContext.class); + assertThat(parent).isNotInstanceOf(WebApplicationContext.class); + } + + @Configuration + protected static class ParentConfiguration extends AbstractConfig { + + } + + @Configuration + @EnableWebMvc + @RestController + protected static class ChildConfiguration extends AbstractConfig { + + } + +}