diff --git a/spring-test/src/main/java/org/springframework/test/context/NestedTestConfiguration.java b/spring-test/src/main/java/org/springframework/test/context/NestedTestConfiguration.java index 4c7d42006e3..570524371fe 100644 --- a/spring-test/src/main/java/org/springframework/test/context/NestedTestConfiguration.java +++ b/spring-test/src/main/java/org/springframework/test/context/NestedTestConfiguration.java @@ -30,13 +30,13 @@ import java.lang.annotation.Target; * *

If {@code @NestedTestConfiguration} is not present or * meta-present on a test class, configuration from the test class will - * not propagate to inner test classes (see {@link EnclosingConfiguration#OVERRIDE}). - * Consequently, inner test classes will have to declare their own Spring test - * configuration annotations. If you wish for an inner test class to inherit - * configuration from its enclosing class, annotate either the inner test class - * or the enclosing class with - * {@code @NestedTestConfiguration(EnclosingConfiguration.INHERIT)}. Note that - * a {@code @NestedTestConfiguration(...)} declaration is inherited within the + * propagate to inner test classes (see {@link EnclosingConfiguration#INHERIT}). + * If {@code @NestedTestConfiguration(OVERRIDE)} is used to switch the mode, + * inner test classes will have to declare their own Spring test configuration + * annotations. If you wish to explicitly configure the mode, annotate either + * the inner test class or the enclosing class with + * {@code @NestedTestConfiguration(...}. Note that a + * {@code @NestedTestConfiguration(...)} declaration is inherited within the * superclass hierarchy as well as within the enclosing class hierarchy. Thus, * there is no need to redeclare the annotation unless you wish to switch the * mode. diff --git a/spring-test/src/main/java/org/springframework/test/util/MetaAnnotationUtils.java b/spring-test/src/main/java/org/springframework/test/util/MetaAnnotationUtils.java index cee1b4d56bb..26aeb565c1b 100644 --- a/spring-test/src/main/java/org/springframework/test/util/MetaAnnotationUtils.java +++ b/spring-test/src/main/java/org/springframework/test/util/MetaAnnotationUtils.java @@ -68,8 +68,8 @@ import org.springframework.util.ObjectUtils; */ public abstract class MetaAnnotationUtils { - private static final ConcurrentLruCache, SearchStrategy> cachedSearchStrategies = - new ConcurrentLruCache<>(32, MetaAnnotationUtils::lookUpSearchStrategy); + private static final ConcurrentLruCache, EnclosingConfiguration> cachedSearchStrategies = + new ConcurrentLruCache<>(32, MetaAnnotationUtils::lookUpEnclosingConfiguration); /** @@ -301,35 +301,29 @@ public abstract class MetaAnnotationUtils { * class should be searched * @since 5.3 * @see ClassUtils#isInnerClass(Class) - * @see #getSearchStrategy(Class) */ public static boolean searchEnclosingClass(Class clazz) { return (ClassUtils.isInnerClass(clazz) && - getSearchStrategy(clazz) == SearchStrategy.TYPE_HIERARCHY_AND_ENCLOSING_CLASSES); + getEnclosingConfiguration(clazz) == EnclosingConfiguration.INHERIT); } /** - * Get the {@link SearchStrategy} for the supplied class. + * Get the {@link EnclosingConfiguration} mode for the supplied class. * @param clazz the class for which the search strategy should be resolved * @return the resolved search strategy * @since 5.3 */ - private static SearchStrategy getSearchStrategy(Class clazz) { + private static EnclosingConfiguration getEnclosingConfiguration(Class clazz) { return cachedSearchStrategies.get(clazz); } - private static SearchStrategy lookUpSearchStrategy(Class clazz) { - EnclosingConfiguration enclosingConfiguration = - MergedAnnotations.from(clazz, SearchStrategy.TYPE_HIERARCHY_AND_ENCLOSING_CLASSES) + private static EnclosingConfiguration lookUpEnclosingConfiguration(Class clazz) { + // TODO Make the default EnclosingConfiguration mode globally configurable via SpringProperties. + return MergedAnnotations.from(clazz, SearchStrategy.TYPE_HIERARCHY_AND_ENCLOSING_CLASSES) .stream(NestedTestConfiguration.class) .map(mergedAnnotation -> mergedAnnotation.getEnum("value", EnclosingConfiguration.class)) .findFirst() - .orElse(EnclosingConfiguration.OVERRIDE); - // TODO Switch the default EnclosingConfiguration mode to INHERIT. - // TODO Make the default EnclosingConfiguration mode globally configurable via SpringProperties. - return (enclosingConfiguration == EnclosingConfiguration.INHERIT ? - SearchStrategy.TYPE_HIERARCHY_AND_ENCLOSING_CLASSES : - SearchStrategy.TYPE_HIERARCHY); + .orElse(EnclosingConfiguration.INHERIT); } private static void assertNonEmptyAnnotationTypeArray(Class[] annotationTypes, String message) { @@ -505,10 +499,12 @@ public abstract class MetaAnnotationUtils { */ @SuppressWarnings("unchecked") public Set findAllLocalMergedAnnotations() { - Class annotationType = (Class) getAnnotationType(); - SearchStrategy searchStrategy = getSearchStrategy(getRootDeclaringClass()); + SearchStrategy searchStrategy = + (getEnclosingConfiguration(getRootDeclaringClass()) == EnclosingConfiguration.INHERIT ? + SearchStrategy.TYPE_HIERARCHY_AND_ENCLOSING_CLASSES : + SearchStrategy.TYPE_HIERARCHY); return MergedAnnotations.from(getRootDeclaringClass(), searchStrategy, RepeatableContainers.none()) - .stream(annotationType) + .stream((Class) getAnnotationType()) .filter(MergedAnnotationPredicates.firstRunOf(MergedAnnotation::getAggregateIndex)) .collect(MergedAnnotationCollectors.toAnnotationSet()); } diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ActiveProfilesNestedTests.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ActiveProfilesNestedTests.java index 2a999775ef0..b4de8d1bae7 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ActiveProfilesNestedTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ActiveProfilesNestedTests.java @@ -46,6 +46,7 @@ import static org.springframework.test.context.NestedTestConfiguration.Enclosing */ @SpringJUnitConfig(Config1.class) @ActiveProfiles("1") +@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default class ActiveProfilesNestedTests { @Autowired diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ConstructorInjectionNestedTests.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ConstructorInjectionNestedTests.java index c0decfb517c..2cd988ae8a0 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ConstructorInjectionNestedTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ConstructorInjectionNestedTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2020 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. @@ -25,12 +25,14 @@ import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.NestedTestConfiguration; import org.springframework.test.context.junit.SpringJUnitJupiterTestSuite; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.springframework.test.context.junit.jupiter.nested.ConstructorInjectionNestedTests.TopLevelConfig; import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.OVERRIDE; /** * Integration tests that verify support for {@code @Nested} test classes in conjunction @@ -47,6 +49,7 @@ import static org.assertj.core.api.Assertions.assertThat; * @see org.springframework.test.context.junit4.nested.NestedTestsWithSpringRulesTests */ @SpringJUnitConfig(TopLevelConfig.class) +@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default class ConstructorInjectionNestedTests { final String foo; diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextConfigurationNestedTests.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextConfigurationNestedTests.java index 80770ba7e40..cedcb5788ab 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextConfigurationNestedTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextConfigurationNestedTests.java @@ -44,6 +44,7 @@ import static org.springframework.test.context.NestedTestConfiguration.Enclosing * @see org.springframework.test.context.junit4.nested.NestedTestsWithSpringRulesTests */ @SpringJUnitConfig(TopLevelConfig.class) +@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default class ContextConfigurationNestedTests { private static final String FOO = "foo"; diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextHierarchyNestedTests.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextHierarchyNestedTests.java index 909af00a372..a0f86af93a6 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextHierarchyNestedTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextHierarchyNestedTests.java @@ -45,6 +45,7 @@ import static org.springframework.test.context.NestedTestConfiguration.Enclosing */ @ExtendWith(SpringExtension.class) @ContextHierarchy(@ContextConfiguration(classes = ParentConfig.class)) +@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default class ContextHierarchyNestedTests { private static final String FOO = "foo"; diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/SqlScriptNestedTests.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/SqlScriptNestedTests.java index bea6c8dc526..2dc297f2e1a 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/SqlScriptNestedTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/SqlScriptNestedTests.java @@ -67,12 +67,6 @@ class SqlScriptNestedTests { } @Nested - // NOTE: the following @SpringJUnitConfig declaration must NOT be removed. - // This was added before the TestContext framework looked up configuration - // on enclosing classes for @Nested test classes. As such, this serves as a - // regression test and cannot be changed. - @SpringJUnitConfig(PopulatedSchemaDatabaseConfig.class) - @Transactional class NestedTests { @Autowired diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestConstructorNestedTests.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestConstructorNestedTests.java index 26aee5af305..db2be703240 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestConstructorNestedTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestConstructorNestedTests.java @@ -43,6 +43,7 @@ import static org.springframework.test.context.TestConstructor.AutowireMode.ANNO */ @SpringJUnitConfig @TestConstructor(autowireMode = ALL) +@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default class TestConstructorNestedTests { TestConstructorNestedTests(String text) { diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestExecutionListenersNestedTests.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestExecutionListenersNestedTests.java index c41d1b036f6..2d49ece5250 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestExecutionListenersNestedTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestExecutionListenersNestedTests.java @@ -46,6 +46,7 @@ import static org.springframework.test.context.NestedTestConfiguration.Enclosing */ @SpringJUnitConfig @TestExecutionListeners(FooTestExecutionListener.class) +@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default class TestExecutionListenersNestedTests { private static final String FOO = "foo"; diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestPropertySourceNestedTests.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestPropertySourceNestedTests.java index 2423b63f3c0..fe42ec6d676 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestPropertySourceNestedTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestPropertySourceNestedTests.java @@ -42,6 +42,7 @@ import static org.springframework.test.context.NestedTestConfiguration.Enclosing */ @SpringJUnitConfig(Config.class) @TestPropertySource(properties = "p1 = v1") +@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default class TestPropertySourceNestedTests { @Autowired @@ -160,6 +161,12 @@ class TestPropertySourceNestedTests { } @Nested + // The following explicit INHERIT is necessary since this nested + // test class implements an interface whose enclosing class is + // annotated with @NestedTestConfiguration(OVERRIDE). In other + // words, the local declaration overrides the declaration + // "inherited" via the interface. + @NestedTestConfiguration(INHERIT) class L5WithInheritedConfigAndTestInterfaceTests implements TestInterface { @Autowired diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TransactionalNestedTests.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TransactionalNestedTests.java index 281c4cdcd85..e6121e38e37 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TransactionalNestedTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TransactionalNestedTests.java @@ -53,6 +53,7 @@ import static org.springframework.transaction.annotation.Propagation.NOT_SUPPORT @SpringJUnitConfig @Transactional @Commit +@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default class TransactionalNestedTests { @Test diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/WebAppConfigurationNestedTests.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/WebAppConfigurationNestedTests.java index d62de1b2afe..70c94da2b33 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/WebAppConfigurationNestedTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/WebAppConfigurationNestedTests.java @@ -44,6 +44,7 @@ import static org.springframework.test.context.NestedTestConfiguration.Enclosing * @see org.springframework.test.context.junit4.nested.NestedTestsWithSpringRulesTests */ @SpringJUnitWebConfig(Config.class) +@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default class WebAppConfigurationNestedTests { @Test