diff --git a/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootConfigurationFinder.java b/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootConfigurationFinder.java new file mode 100644 index 0000000000..84a8112ef2 --- /dev/null +++ b/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootConfigurationFinder.java @@ -0,0 +1,102 @@ +/* + * Copyright 2012-2016 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 java.util.Collections; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; +import org.springframework.core.type.filter.AnnotationTypeFilter; +import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; + +/** + * Internal utility class to scan for a {@link SpringBootConfiguration} class. + * + * @author Phillip Webb + */ +final class SpringBootConfigurationFinder { + + private static final Map> cache = Collections + .synchronizedMap(new Cache(40)); + + private final ClassPathScanningCandidateComponentProvider scanner; + + SpringBootConfigurationFinder() { + this.scanner = new ClassPathScanningCandidateComponentProvider(false); + this.scanner.addIncludeFilter( + new AnnotationTypeFilter(SpringBootConfiguration.class)); + this.scanner.setResourcePattern("*.class"); + } + + public Class findFromClass(Class source) { + Assert.notNull(source, "Source must not be null"); + return findFromPackage(ClassUtils.getPackageName(source)); + } + + public Class findFromPackage(String source) { + Assert.notNull(source, "Source must not be null"); + Class configuration = cache.get(source); + if (configuration == null) { + configuration = scanPackage(source); + cache.put(source, configuration); + } + return configuration; + } + + private Class scanPackage(String source) { + while (source.length() > 0) { + Set components = this.scanner.findCandidateComponents(source); + if (!components.isEmpty()) { + Assert.state(components.size() == 1, + "Found multiple @SpringBootConfiguration annotated classes"); + return ClassUtils.resolveClassName( + components.iterator().next().getBeanClassName(), null); + } + source = getParentPackage(source); + } + return null; + } + + private String getParentPackage(String sourcePackage) { + int lastDot = sourcePackage.lastIndexOf("."); + return (lastDot == -1 ? "" : sourcePackage.substring(0, lastDot)); + } + + /** + * Cache implementation based on {@link LinkedHashMap}. + */ + private static class Cache extends LinkedHashMap> { + + private final int maxSize; + + Cache(int maxSize) { + super(16, 0.75f, true); + this.maxSize = maxSize; + } + + @Override + protected boolean removeEldestEntry(Map.Entry> eldest) { + return size() > this.maxSize; + } + + } +} 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 new file mode 100644 index 0000000000..7dcc79f5ee --- /dev/null +++ b/spring-boot-test/src/main/java/org/springframework/boot/test/context/SpringBootTestContextBootstrapper.java @@ -0,0 +1,138 @@ +/* + * Copyright 2012-2016 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 java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.core.annotation.AnnotatedElementUtils; +import org.springframework.test.context.ContextLoader; +import org.springframework.test.context.MergedContextConfiguration; +import org.springframework.test.context.TestContextBootstrapper; +import org.springframework.test.context.support.DefaultTestContextBootstrapper; +import org.springframework.util.Assert; + +/** + * {@link TestContextBootstrapper} that uses {@link SpringApplicationContextLoader} and + * can automatically find the {@link SpringBootConfiguration @SpringBootConfiguration}. + * + * @author Phillip Webb + * @since 1.4.0 + * @see TestConfiguration + */ +public class SpringBootTestContextBootstrapper extends DefaultTestContextBootstrapper { + + private static final Log logger = LogFactory + .getLog(SpringBootTestContextBootstrapper.class); + + @Override + protected Class getDefaultContextLoaderClass( + Class testClass) { + return SpringApplicationContextLoader.class; + } + + @Override + protected MergedContextConfiguration processMergedContextConfiguration( + MergedContextConfiguration mergedConfig) { + Class[] classes = getOrFindConfigurationClasses(mergedConfig); + List propertySourceProperties = getAndProcessPropertySourceProperties( + mergedConfig); + return new MergedContextConfiguration(mergedConfig.getTestClass(), + mergedConfig.getLocations(), classes, + mergedConfig.getContextInitializerClasses(), + mergedConfig.getActiveProfiles(), + mergedConfig.getPropertySourceLocations(), + propertySourceProperties + .toArray(new String[propertySourceProperties.size()]), + mergedConfig.getContextCustomizers(), mergedConfig.getContextLoader(), + getCacheAwareContextLoaderDelegate(), mergedConfig.getParent()); + } + + protected Class[] getOrFindConfigurationClasses( + MergedContextConfiguration mergedConfig) { + Class[] classes = mergedConfig.getClasses(); + if (containsNonTestComponent(classes) || mergedConfig.hasLocations() + || !mergedConfig.getContextInitializerClasses().isEmpty()) { + return classes; + } + Class found = new SpringBootConfigurationFinder() + .findFromClass(mergedConfig.getTestClass()); + Assert.state(found != null, + "Unable to find a @SpringBootConfiguration, you need to use " + + "@ContextConfiguration or @SpringApplicationConfiguration " + + "with your test"); + logger.info("Found @SpringBootConfiguration " + found.getName() + " for test " + + mergedConfig.getTestClass()); + return merge(found, classes); + } + + private boolean containsNonTestComponent(Class[] classes) { + for (Class candidate : classes) { + if (!AnnotatedElementUtils.isAnnotated(candidate, TestConfiguration.class)) { + return true; + } + } + return false; + } + + private Class[] merge(Class head, Class[] existing) { + Class[] result = new Class[existing.length + 1]; + result[0] = head; + System.arraycopy(existing, 0, result, 1, existing.length); + return result; + } + + private List getAndProcessPropertySourceProperties( + MergedContextConfiguration mergedConfig) { + List propertySourceProperties = new ArrayList( + Arrays.asList(mergedConfig.getPropertySourceProperties())); + String differentiator = getDifferentiatorPropertySourceProperty(); + if (differentiator != null) { + propertySourceProperties.add(differentiator); + } + processPropertySourceProperties(mergedConfig, propertySourceProperties); + return propertySourceProperties; + } + + /** + * Return a "differentiator" property to ensure that there is something to + * differentiate regular tests and bootstrapped tests. Without this property a cached + * context could be returned that wasn't created by this bootstrapper. By default uses + * the bootstrapper class as a property. + * @return the differentator or {@code null} + */ + protected String getDifferentiatorPropertySourceProperty() { + return getClass().getName() + "=true"; + } + + /** + * Post process the property source properties, adding or removing elements as + * required. + * @param mergedConfig the merged context configuration + * @param propertySourceProperties the property source properties to process + */ + protected void processPropertySourceProperties( + MergedContextConfiguration mergedConfig, + List propertySourceProperties) { + } + +} diff --git a/spring-boot-test/src/main/java/org/springframework/boot/test/context/TestConfiguration.java b/spring-boot-test/src/main/java/org/springframework/boot/test/context/TestConfiguration.java new file mode 100644 index 0000000000..89cf5fba93 --- /dev/null +++ b/spring-boot-test/src/main/java/org/springframework/boot/test/context/TestConfiguration.java @@ -0,0 +1,51 @@ +/* + * Copyright 2012-2016 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 java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.context.annotation.Configuration; + +/** + * {@link Configuration @Configuration} that can be used to define additional beans or + * customizations for a test. Unlike regular {@code @Configuration} classes the use of + * {@code @TestConfiguration} does not prevent auto-detection of + * {@link SpringBootConfiguration @SpringBootConfiguration}. + * + * @author Phillip Webb + * @since 1.4.0 + * @see SpringBootTestContextBootstrapper + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Configuration +@TestComponent +public @interface TestConfiguration { + + /** + * Explicitly specify the name of the Spring bean definition associated with this + * Configuration class. See {@link Configuration#value()} for details. + */ + String value() default ""; + +} diff --git a/spring-boot-test/src/main/java/org/springframework/boot/test/context/web/WebAppIntegrationTestContextBootstrapper.java b/spring-boot-test/src/main/java/org/springframework/boot/test/context/web/WebAppIntegrationTestContextBootstrapper.java index 2af5c5ba91..3356146499 100644 --- a/spring-boot-test/src/main/java/org/springframework/boot/test/context/web/WebAppIntegrationTestContextBootstrapper.java +++ b/spring-boot-test/src/main/java/org/springframework/boot/test/context/web/WebAppIntegrationTestContextBootstrapper.java @@ -17,34 +17,23 @@ package org.springframework.boot.test.context.web; import org.springframework.boot.test.context.MergedContextConfigurationProperties; +import org.springframework.boot.test.context.SpringBootTestContextBootstrapper; import org.springframework.core.annotation.AnnotatedElementUtils; -import org.springframework.test.context.ContextLoader; import org.springframework.test.context.MergedContextConfiguration; import org.springframework.test.context.TestContextBootstrapper; -import org.springframework.test.context.support.DefaultTestContextBootstrapper; -import org.springframework.test.context.web.WebDelegatingSmartContextLoader; import org.springframework.test.context.web.WebMergedContextConfiguration; /** * {@link TestContextBootstrapper} for Spring Boot web integration tests. * * @author Phillip Webb - * @since 1.2.1 */ -class WebAppIntegrationTestContextBootstrapper extends DefaultTestContextBootstrapper { - - @Override - protected Class getDefaultContextLoaderClass( - Class testClass) { - if (AnnotatedElementUtils.isAnnotated(testClass, WebIntegrationTest.class)) { - return WebDelegatingSmartContextLoader.class; - } - return super.getDefaultContextLoaderClass(testClass); - } +class WebAppIntegrationTestContextBootstrapper extends SpringBootTestContextBootstrapper { @Override protected MergedContextConfiguration processMergedContextConfiguration( MergedContextConfiguration mergedConfig) { + mergedConfig = super.processMergedContextConfiguration(mergedConfig); WebIntegrationTest annotation = AnnotatedElementUtils.findMergedAnnotation( mergedConfig.getTestClass(), WebIntegrationTest.class); if (annotation != null) { diff --git a/spring-boot-test/src/test/java/org/springframework/boot/test/context/SpringBootConfigurationFinderTests.java b/spring-boot-test/src/test/java/org/springframework/boot/test/context/SpringBootConfigurationFinderTests.java new file mode 100644 index 0000000000..a08192647f --- /dev/null +++ b/spring-boot-test/src/test/java/org/springframework/boot/test/context/SpringBootConfigurationFinderTests.java @@ -0,0 +1,73 @@ +/* + * Copyright 2012-2016 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.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import org.springframework.boot.test.context.example.ExampleConfig; +import org.springframework.boot.test.context.example.scan.Example; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link SpringBootConfigurationFinder}. + * + * @author Phillip Webb + */ +public class SpringBootConfigurationFinderTests { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + private SpringBootConfigurationFinder finder = new SpringBootConfigurationFinder(); + + @Test + public void findFromClassWhenSourceIsNullShouldThrowException() throws Exception { + this.thrown.expect(IllegalArgumentException.class); + this.thrown.expectMessage("Source must not be null"); + this.finder.findFromClass((Class) null); + } + + @Test + public void findFromPackageWhenSourceIsNullShouldThrowException() throws Exception { + this.thrown.expect(IllegalArgumentException.class); + this.thrown.expectMessage("Source must not be null"); + this.finder.findFromPackage((String) null); + } + + @Test + public void findFromPackageWhenNoConfigurationFoundShouldReturnNull() { + Class config = this.finder.findFromPackage("org.springframework.boot"); + assertThat(config).isNull(); + } + + @Test + public void findFromClassWhenConfigurationIsFoundShouldReturnConfiguration() { + Class config = this.finder.findFromClass(Example.class); + assertThat(config).isEqualTo(ExampleConfig.class); + } + + @Test + public void findFromPackageWhenConfigurationIsFoundShouldReturnConfiguration() { + Class config = this.finder + .findFromPackage("org.springframework.boot.test.context.example.scan"); + assertThat(config).isEqualTo(ExampleConfig.class); + } + +} diff --git a/spring-boot-test/src/test/java/org/springframework/boot/test/context/bootstrap/SpringBootTestContextBootstrapperExampleConfig.java b/spring-boot-test/src/test/java/org/springframework/boot/test/context/bootstrap/SpringBootTestContextBootstrapperExampleConfig.java new file mode 100644 index 0000000000..080441e12c --- /dev/null +++ b/spring-boot-test/src/test/java/org/springframework/boot/test/context/bootstrap/SpringBootTestContextBootstrapperExampleConfig.java @@ -0,0 +1,29 @@ +/* + * Copyright 2012-2016 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.bootstrap; + +import org.springframework.boot.SpringBootConfiguration; + +/** + * Example configuration used in {@link SpringBootTestContextBootstrapperTests}. + * + * @author Phillip Webb + */ +@SpringBootConfiguration +public class SpringBootTestContextBootstrapperExampleConfig { + +} diff --git a/spring-boot-test/src/test/java/org/springframework/boot/test/context/bootstrap/SpringBootTestContextBootstrapperTests.java b/spring-boot-test/src/test/java/org/springframework/boot/test/context/bootstrap/SpringBootTestContextBootstrapperTests.java new file mode 100644 index 0000000000..176f416d41 --- /dev/null +++ b/spring-boot-test/src/test/java/org/springframework/boot/test/context/bootstrap/SpringBootTestContextBootstrapperTests.java @@ -0,0 +1,82 @@ +/* + * Copyright 2012-2016 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.bootstrap; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTestContextBootstrapper; +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.stereotype.Component; +import org.springframework.test.context.BootstrapWith; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link SpringBootTestContextBootstrapper} (in its own package so we can test + * detection). + * + * @author Phillip Webb + */ +@RunWith(SpringRunner.class) +@BootstrapWith(SpringBootTestContextBootstrapper.class) +public class SpringBootTestContextBootstrapperTests { + + @Autowired + private ApplicationContext context; + + @Autowired + private SpringBootTestContextBootstrapperExampleConfig config; + + @Test + public void findConfigAutomatically() throws Exception { + assertThat(this.config).isNotNull(); + } + + @Test + public void contextWasCreatedViaSpringApplication() throws Exception { + assertThat(this.context.getId()).startsWith("application:"); + } + + @Test + public void testConfigurationWasApplied() throws Exception { + assertThat(this.context.getBean(ExampleBean.class)).isNotNull(); + } + + @TestConfiguration + static class TestConfig { + + @Bean + public ExampleBean exampleBean() { + return new ExampleBean(); + } + + } + + static class ExampleBean { + + } + + @Component + static class ExampleTestComponent { + + } +} diff --git a/spring-boot-test/src/test/java/org/springframework/boot/test/context/bootstrap/SpringBootTestContextBootstrapperWithContextConfigurationTests.java b/spring-boot-test/src/test/java/org/springframework/boot/test/context/bootstrap/SpringBootTestContextBootstrapperWithContextConfigurationTests.java new file mode 100644 index 0000000000..45b724aaa7 --- /dev/null +++ b/spring-boot-test/src/test/java/org/springframework/boot/test/context/bootstrap/SpringBootTestContextBootstrapperWithContextConfigurationTests.java @@ -0,0 +1,58 @@ +/* + * Copyright 2012-2016 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.bootstrap; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTestContextBootstrapper; +import org.springframework.context.ApplicationContext; +import org.springframework.test.context.BootstrapWith; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Tests for {@link SpringBootTestContextBootstrapper} + {@code @ContextConfiguration} (in + * its own package so we can test detection). + * + * @author Phillip Webb + */ +@RunWith(SpringRunner.class) +@BootstrapWith(SpringBootTestContextBootstrapper.class) +@ContextConfiguration +public class SpringBootTestContextBootstrapperWithContextConfigurationTests { + + @Autowired + private ApplicationContext context; + + @Autowired + private SpringBootTestContextBootstrapperExampleConfig config; + + @Test + public void findConfigAutomatically() throws Exception { + assertThat(this.config).isNotNull(); + } + + @Test + public void contextWasCreatedViaSpringApplication() throws Exception { + assertThat(this.context.getId()).startsWith("application:"); + } + +} diff --git a/spring-boot-test/src/test/java/org/springframework/boot/test/context/example/ExampleConfig.java b/spring-boot-test/src/test/java/org/springframework/boot/test/context/example/ExampleConfig.java new file mode 100644 index 0000000000..6af5bbbaba --- /dev/null +++ b/spring-boot-test/src/test/java/org/springframework/boot/test/context/example/ExampleConfig.java @@ -0,0 +1,30 @@ +/* + * Copyright 2012-2016 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.example; + +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.test.context.SpringBootConfigurationFinderTests; + +/** + * Example config used in {@link SpringBootConfigurationFinderTests}. + * + * @author Phillip Webb + */ +@SpringBootConfiguration +public class ExampleConfig { + +} diff --git a/spring-boot-test/src/test/java/org/springframework/boot/test/context/example/scan/Example.java b/spring-boot-test/src/test/java/org/springframework/boot/test/context/example/scan/Example.java new file mode 100644 index 0000000000..cf266e5eb4 --- /dev/null +++ b/spring-boot-test/src/test/java/org/springframework/boot/test/context/example/scan/Example.java @@ -0,0 +1,28 @@ +/* + * Copyright 2012-2016 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.example.scan; + +import org.springframework.boot.test.context.SpringBootConfigurationFinderTests; + +/** + * Example class used in {@link SpringBootConfigurationFinderTests}. + * + * @author Phillip Webb + */ +public class Example { + +} diff --git a/spring-boot-test/src/test/java/org/springframework/boot/test/context/example/scan/sub/SubExampleConfig.java b/spring-boot-test/src/test/java/org/springframework/boot/test/context/example/scan/sub/SubExampleConfig.java new file mode 100644 index 0000000000..bd49c8b911 --- /dev/null +++ b/spring-boot-test/src/test/java/org/springframework/boot/test/context/example/scan/sub/SubExampleConfig.java @@ -0,0 +1,31 @@ +/* + * Copyright 2012-2016 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.example.scan.sub; + +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.test.context.SpringBootConfigurationFinderTests; + +/** + * Example config used in {@link SpringBootConfigurationFinderTests}. Should not be found + * since scanner should only search upwards. + * + * @author Phillip Webb + */ +@SpringBootConfiguration +public class SubExampleConfig { + +}