diff --git a/spring-test/src/main/java/org/springframework/test/context/ContextConfiguration.java b/spring-test/src/main/java/org/springframework/test/context/ContextConfiguration.java index e8ff6c0186d..cb07e6fef99 100644 --- a/spring-test/src/main/java/org/springframework/test/context/ContextConfiguration.java +++ b/spring-test/src/main/java/org/springframework/test/context/ContextConfiguration.java @@ -80,6 +80,8 @@ import org.springframework.core.annotation.AliasFor; * * @author Sam Brannen * @since 2.5 + * @see org.springframework.test.context.junit.jupiter.SpringExtension SpringExtension + * @see org.springframework.test.context.junit.jupiter.SpringExtensionConfig @SpringExtensionConfig * @see org.springframework.test.context.junit.jupiter.SpringJUnitConfig @SpringJUnitConfig * @see org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig @SpringJUnitWebConfig * @see ContextHierarchy @ContextHierarchy 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 05fb2b1cfee..fb4576ff181 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 @@ -95,6 +95,9 @@ import org.jspecify.annotations.Nullable; *
  • {@link TestConstructor @TestConstructor}
  • * * + *

    Note that {@code @NestedTestConfiguration} does not apply to + * {@link org.springframework.test.context.junit.jupiter.SpringExtensionConfig @SpringExtensionConfig}. + * * @author Sam Brannen * @since 5.3 * @see EnclosingConfiguration#INHERIT diff --git a/spring-test/src/main/java/org/springframework/test/context/TestConstructor.java b/spring-test/src/main/java/org/springframework/test/context/TestConstructor.java index 219c94cab8c..9803c83438b 100644 --- a/spring-test/src/main/java/org/springframework/test/context/TestConstructor.java +++ b/spring-test/src/main/java/org/springframework/test/context/TestConstructor.java @@ -61,6 +61,7 @@ import org.jspecify.annotations.Nullable; * @see org.springframework.beans.factory.annotation.Autowired @Autowired * @see jakarta.inject.Inject @jakarta.inject.Inject * @see org.springframework.test.context.junit.jupiter.SpringExtension SpringExtension + * @see org.springframework.test.context.junit.jupiter.SpringExtensionConfig @SpringExtensionConfig * @see org.springframework.test.context.junit.jupiter.SpringJUnitConfig @SpringJUnitConfig * @see org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig @SpringJUnitWebConfig * @see ContextConfiguration @ContextConfiguration diff --git a/spring-test/src/main/java/org/springframework/test/context/TestContext.java b/spring-test/src/main/java/org/springframework/test/context/TestContext.java index 87816cadfcd..4cb97c5db5c 100644 --- a/spring-test/src/main/java/org/springframework/test/context/TestContext.java +++ b/spring-test/src/main/java/org/springframework/test/context/TestContext.java @@ -117,6 +117,7 @@ public interface TestContext extends AttributeAccessor, Serializable { * invoke {@code testContext.getTestInstance().getClass()} instead of * {@code testContext.getTestClass()}. * @return the test class (never {@code null}) + * @see org.springframework.test.context.junit.jupiter.SpringExtensionConfig @SpringExtensionConfig */ Class getTestClass(); diff --git a/spring-test/src/main/java/org/springframework/test/context/TestExecutionListener.java b/spring-test/src/main/java/org/springframework/test/context/TestExecutionListener.java index b9f9a96f4cc..81327908d9f 100644 --- a/spring-test/src/main/java/org/springframework/test/context/TestExecutionListener.java +++ b/spring-test/src/main/java/org/springframework/test/context/TestExecutionListener.java @@ -169,6 +169,7 @@ public interface TestExecutionListener { * concrete classes as necessary. * @param testContext the test context for the test; never {@code null} * @throws Exception allows any exception to propagate + * @see org.springframework.test.context.junit.jupiter.SpringExtensionConfig @SpringExtensionConfig */ default void prepareTestInstance(TestContext testContext) throws Exception { } diff --git a/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/SpringExtension.java b/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/SpringExtension.java index fb8c93a32fe..79869d8eb80 100644 --- a/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/SpringExtension.java +++ b/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/SpringExtension.java @@ -48,6 +48,7 @@ import org.junit.platform.commons.annotation.Testable; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.ParameterResolutionDelegate; import org.springframework.context.ApplicationContext; +import org.springframework.core.annotation.MergedAnnotation; import org.springframework.core.annotation.MergedAnnotations; import org.springframework.core.annotation.MergedAnnotations.SearchStrategy; import org.springframework.core.annotation.RepeatableContainers; @@ -59,6 +60,8 @@ import org.springframework.test.context.event.RecordApplicationEvents; import org.springframework.test.context.support.PropertyProvider; import org.springframework.test.context.support.TestConstructorUtils; import org.springframework.util.Assert; +import org.springframework.util.ClassUtils; +import org.springframework.util.ConcurrentLruCache; import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils.MethodFilter; @@ -66,18 +69,37 @@ import org.springframework.util.ReflectionUtils.MethodFilter; * {@code SpringExtension} integrates the Spring TestContext Framework * into the JUnit Jupiter testing framework. * - *

    To use this extension, simply annotate a JUnit Jupiter based test class with - * {@code @ExtendWith(SpringExtension.class)}, {@code @SpringJUnitConfig}, or - * {@code @SpringJUnitWebConfig}. + *

    To use this extension, annotate a JUnit Jupiter based test class with + * {@code @ExtendWith(SpringExtension.class)}, {@code @SpringJUnitConfig}, + * {@code @SpringJUnitWebConfig}, or any other annotation that is meta-annotated + * with {@code @ExtendWith(SpringExtension.class)} such as {@code @SpringBootTest}, + * etc. + * + *

    As of Spring Framework 7.0, the {@code SpringExtension} is + * {@linkplain #getTestInstantiationExtensionContextScope(ExtensionContext) + * configured} to use a test-method scoped {@link ExtensionContext}, which + * enables consistent dependency injection into fields and constructors from the + * {@link ApplicationContext} for the current test method in a + * {@link org.junit.jupiter.api.Nested @Nested} test class hierarchy. However, + * if a third-party {@link org.junit.platform.launcher.TestExecutionListener + * TestExecutionListener} is not compatible with the semantics associated with + * a test-method scoped extension context — or if a developer wishes to + * switch to test-class scoped semantics — the {@code SpringExtension} can + * be configured to use a test-class scoped extension context by annotating a + * top-level test class with + * {@link SpringExtensionConfig#useTestClassScopedExtensionContext() + * @SpringExtensionConfig(useTestClassScopedExtensionContext = true)}. * * @author Sam Brannen * @author Simon BaslĂ© * @since 5.0 - * @see org.springframework.test.context.junit.jupiter.EnabledIf - * @see org.springframework.test.context.junit.jupiter.DisabledIf - * @see org.springframework.test.context.junit.jupiter.SpringJUnitConfig - * @see org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig - * @see org.springframework.test.context.TestContextManager + * @see org.junit.jupiter.api.extension.ExtendWith @ExtendWith + * @see org.springframework.test.context.junit.jupiter.SpringExtensionConfig @SpringExtensionConfig + * @see org.springframework.test.context.junit.jupiter.SpringJUnitConfig @SpringJUnitConfig + * @see org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig @SpringJUnitWebConfig + * @see org.springframework.test.context.junit.jupiter.EnabledIf @EnabledIf + * @see org.springframework.test.context.junit.jupiter.DisabledIf @DisabledIf + * @see org.springframework.test.context.TestContextManager TestContextManager */ public class SpringExtension implements BeforeAllCallback, AfterAllCallback, TestInstancePostProcessor, BeforeEachCallback, AfterEachCallback, BeforeTestExecutionCallback, AfterTestExecutionCallback, @@ -110,6 +132,14 @@ public class SpringExtension implements BeforeAllCallback, AfterAllCallback, Tes private static final Namespace RECORD_APPLICATION_EVENTS_VALIDATION_NAMESPACE = Namespace.create(SpringExtension.class.getName() + "#recordApplicationEvents.validation"); + /** + * LRU cache for {@link SpringExtensionConfig#useTestClassScopedExtensionContext()} + * mappings, keyed by test class. + * @since 7.0 + */ + private static final ConcurrentLruCache, Boolean> useTestClassScopedExtensionContextCache = + new ConcurrentLruCache<>(32, SpringExtension::useTestClassScopedExtensionContext); + // Note that @Test, @TestFactory, @TestTemplate, @RepeatedTest, and @ParameterizedTest // are all meta-annotated with @Testable. private static final List> JUPITER_ANNOTATION_TYPES = @@ -119,6 +149,19 @@ public class SpringExtension implements BeforeAllCallback, AfterAllCallback, Tes ReflectionUtils.USER_DECLARED_METHODS.and(SpringExtension::isAutowiredTestOrLifecycleMethod); + /** + * Returns {@link ExtensionContextScope#TEST_METHOD ExtensionContextScope.TEST_METHOD}. + *

    This can be effectively overridden by annotating a test class with + * {@code @SpringExtensionConfig(useTestClassScopedExtensionContext = true)}. + * See the {@link SpringExtension class-level Javadoc} for further details. + * @since 7.0 + * @see SpringExtensionConfig#useTestClassScopedExtensionContext() + */ + @Override + public ExtensionContextScope getTestInstantiationExtensionContextScope(ExtensionContext rootContext) { + return ExtensionContextScope.TEST_METHOD; + } + /** * Delegates to {@link TestContextManager#beforeTestClass}. */ @@ -151,6 +194,8 @@ public class SpringExtension implements BeforeAllCallback, AfterAllCallback, Tes */ @Override public void postProcessTestInstance(Object testInstance, ExtensionContext context) throws Exception { + context = findProperlyScopedExtensionContext(testInstance.getClass(), context); + validateAutowiredConfig(context); validateRecordApplicationEventsConfig(context); TestContextManager testContextManager = getTestContextManager(context); @@ -332,7 +377,13 @@ public class SpringExtension implements BeforeAllCallback, AfterAllCallback, Tes public @Nullable Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { Parameter parameter = parameterContext.getParameter(); int index = parameterContext.getIndex(); + Executable executable = parameterContext.getDeclaringExecutable(); Class testClass = extensionContext.getRequiredTestClass(); + if (executable instanceof Constructor constructor) { + testClass = constructor.getDeclaringClass(); + extensionContext = findProperlyScopedExtensionContext(testClass, extensionContext); + } + ApplicationContext applicationContext = getApplicationContext(extensionContext); return ParameterResolutionDelegate.resolveDependency(parameter, index, testClass, applicationContext.getAutowireCapableBeanFactory()); @@ -390,4 +441,53 @@ public class SpringExtension implements BeforeAllCallback, AfterAllCallback, Tes return false; } + /** + * Find the properly {@linkplain ExtensionContextScope scoped} {@link ExtensionContext} + * for the supplied test class. + *

    If the supplied {@code ExtensionContext} is already properly scoped, it + * will be returned. Otherwise, if the test class is annotated with + * {@code @SpringExtensionConfig(useTestClassScopedExtensionContext = true)}, + * this method searches the {@code ExtensionContext} hierarchy for an + * {@code ExtensionContext} whose test class is the same as the supplied + * test class. + * @since 7.0 + * @see SpringExtensionConfig#useTestClassScopedExtensionContext() + * @see ExtensionContextScope + */ + private static ExtensionContext findProperlyScopedExtensionContext(Class testClass, ExtensionContext context) { + if (useTestClassScopedExtensionContextCache.get(testClass)) { + while (context.getRequiredTestClass() != testClass) { + context = context.getParent().get(); + } + } + return context; + } + + /** + * Determine if the supplied test class, or one of its enclosing classes, is annotated + * with {@code @SpringExtensionConfig(useTestClassScopedExtensionContext = true)}. + * @since 7.0 + * @see SpringExtensionConfig#useTestClassScopedExtensionContext() + * @see #useTestClassScopedExtensionContextCache + */ + private static boolean useTestClassScopedExtensionContext(Class testClass) { + MergedAnnotation mergedAnnotation = + MergedAnnotations.search(SearchStrategy.TYPE_HIERARCHY) + .withEnclosingClasses(ClassUtils::isInnerClass) + .from(testClass) + .get(SpringExtensionConfig.class); + + if (mergedAnnotation.isPresent()) { + if (mergedAnnotation.getSource() instanceof Class source && ClassUtils.isInnerClass(source)) { + throw new IllegalStateException(""" + Test class [%s] must not be annotated with @SpringExtensionConfig. \ + @SpringExtensionConfig is only supported on top-level classes.\ + """.formatted(source.getName())); + } + return mergedAnnotation.getBoolean("useTestClassScopedExtensionContext"); + } + + return false; + } + } diff --git a/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/SpringExtensionConfig.java b/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/SpringExtensionConfig.java new file mode 100644 index 00000000000..d7209e7654e --- /dev/null +++ b/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/SpringExtensionConfig.java @@ -0,0 +1,68 @@ +/* + * Copyright 2002-present 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 + * + * https://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.test.context.junit.jupiter; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * {@code @SpringExtensionConfig} is a type-level annotation that can be used to + * configure the behavior of the {@link SpringExtension}. + * + *

    This annotation is only applicable to {@link org.junit.jupiter.api.Nested @Nested} + * test class hierarchies and should be applied to the top-level enclosing class + * of a {@code @Nested} test class hierarchy. Consequently, there is no need to + * declare this annotation on a test class that does not contain {@code @Nested} + * test classes. + * + *

    Note that + * {@link org.springframework.test.context.NestedTestConfiguration @NestedTestConfiguration} + * does not apply to this annotation: {@code @SpringExtensionConfig} will always be + * detected within a {@code @Nested} test class hierarchy, effectively disregarding + * any {@code @NestedTestConfiguration(OVERRIDE)} declarations. + * + * @author Sam Brannen + * @since 7.0 + * @see org.springframework.test.context.junit.jupiter.SpringExtension SpringExtension + * @see org.springframework.test.context.junit.jupiter.SpringJUnitConfig @SpringJUnitConfig + * @see org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig @SpringJUnitWebConfig + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Inherited +public @interface SpringExtensionConfig { + + /** + * Specify whether the {@link SpringExtension} should use a test-class scoped + * {@link org.junit.jupiter.api.extension.ExtensionContext ExtensionContext} + * within {@link org.junit.jupiter.api.Nested @Nested} test class hierarchies. + * + *

    By default, the {@code SpringExtension} uses a test-method scoped + * {@code ExtensionContext}. Thus, there is no need to declare this annotation + * attribute with a value of {@code false}. + * + * @see SpringExtension + * @see SpringExtension#getTestInstantiationExtensionContextScope(org.junit.jupiter.api.extension.ExtensionContext) + */ + boolean useTestClassScopedExtensionContext(); + +} diff --git a/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/SpringJUnitConfig.java b/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/SpringJUnitConfig.java index 6e02a3380e6..0bb986c75f7 100644 --- a/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/SpringJUnitConfig.java +++ b/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/SpringJUnitConfig.java @@ -42,10 +42,11 @@ import org.springframework.test.context.ContextLoader; * * @author Sam Brannen * @since 5.0 - * @see ExtendWith - * @see SpringExtension - * @see ContextConfiguration - * @see org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig + * @see org.junit.jupiter.api.extension.ExtendWith @ExtendWith + * @see org.springframework.test.context.junit.jupiter.SpringExtension SpringExtension + * @see org.springframework.test.context.junit.jupiter.SpringExtensionConfig @SpringExtensionConfig + * @see org.springframework.test.context.junit.ContextConfiguration @ContextConfiguration + * @see org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig @SpringJUnitWebConfig */ @ExtendWith(SpringExtension.class) @ContextConfiguration diff --git a/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/web/SpringJUnitWebConfig.java b/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/web/SpringJUnitWebConfig.java index 4bba082fda8..30dd1d9860d 100644 --- a/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/web/SpringJUnitWebConfig.java +++ b/spring-test/src/main/java/org/springframework/test/context/junit/jupiter/web/SpringJUnitWebConfig.java @@ -45,11 +45,12 @@ import org.springframework.test.context.web.WebAppConfiguration; * * @author Sam Brannen * @since 5.0 - * @see ExtendWith - * @see SpringExtension - * @see ContextConfiguration - * @see WebAppConfiguration - * @see org.springframework.test.context.junit.jupiter.SpringJUnitConfig + * @see org.junit.jupiter.api.extension.ExtendWith @ExtendWith + * @see org.springframework.test.context.junit.jupiter.SpringExtension SpringExtension + * @see org.springframework.test.context.junit.jupiter.SpringExtensionConfig @SpringExtensionConfig + * @see org.springframework.test.context.junit.ContextConfiguration @ContextConfiguration + * @see org.springframework.test.context.web.WebAppConfiguration @WebAppConfiguration + * @see org.springframework.test.context.junit.jupiter.SpringJUnitConfig @SpringJUnitConfig */ @ExtendWith(SpringExtension.class) @ContextConfiguration diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/convention/TestBeanByNameLookupTestClassScopedExtensionContextIntegrationTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/convention/TestBeanByNameLookupTestClassScopedExtensionContextIntegrationTests.java index 6eba56e7bfb..660fcde7ed6 100644 --- a/spring-test/src/test/java/org/springframework/test/context/bean/override/convention/TestBeanByNameLookupTestClassScopedExtensionContextIntegrationTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/convention/TestBeanByNameLookupTestClassScopedExtensionContextIntegrationTests.java @@ -26,6 +26,7 @@ import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; +import org.springframework.test.context.junit.jupiter.SpringExtensionConfig; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import static org.assertj.core.api.Assertions.assertThat; @@ -39,6 +40,7 @@ import static org.assertj.core.api.Assertions.assertThat; * @since 6.2 */ @SpringJUnitConfig +@SpringExtensionConfig(useTestClassScopedExtensionContext = true) public class TestBeanByNameLookupTestClassScopedExtensionContextIntegrationTests { @TestBean(name = "field") diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/convention/TestBeanByNameLookupTestMethodScopedExtensionContextIntegrationTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/convention/TestBeanByNameLookupTestMethodScopedExtensionContextIntegrationTests.java index 2b41f116f46..64a22a09945 100644 --- a/spring-test/src/test/java/org/springframework/test/context/bean/override/convention/TestBeanByNameLookupTestMethodScopedExtensionContextIntegrationTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/convention/TestBeanByNameLookupTestMethodScopedExtensionContextIntegrationTests.java @@ -20,7 +20,6 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope; -import org.junit.platform.testkit.engine.EngineTestKit; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; @@ -28,10 +27,6 @@ import org.springframework.context.annotation.Configuration; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope.DEFAULT_SCOPE_PROPERTY_NAME; -import static org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope.TEST_METHOD; -import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; - /** * Integration tests for {@link TestBean} that use by-name lookup with @@ -41,35 +36,46 @@ import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass * @author Sam Brannen * @since 6.2.13 */ +@SpringJUnitConfig public class TestBeanByNameLookupTestMethodScopedExtensionContextIntegrationTests { + @TestBean(name = "field") + String field; + + @TestBean(name = "methodRenamed1", methodName = "field") + String methodRenamed1; + + static String field() { + return "fieldOverride"; + } + + static String nestedField() { + return "nestedFieldOverride"; + } + @Test - void runTests() { - EngineTestKit.engine("junit-jupiter") - .configurationParameter(DEFAULT_SCOPE_PROPERTY_NAME, TEST_METHOD.name()) - .selectors(selectClass(TestCase.class)) - .execute() - .testEvents() - .assertStatistics(stats -> stats.started(12).succeeded(12).failed(0)); + void fieldHasOverride(ApplicationContext ctx) { + assertThat(ctx.getBean("field")).as("applicationContext").isEqualTo("fieldOverride"); + assertThat(field).as("injection point").isEqualTo("fieldOverride"); } + @Test + void fieldWithMethodNameHasOverride(ApplicationContext ctx) { + assertThat(ctx.getBean("methodRenamed1")).as("applicationContext").isEqualTo("fieldOverride"); + assertThat(methodRenamed1).as("injection point").isEqualTo("fieldOverride"); + } - @SpringJUnitConfig - public static class TestCase { - @TestBean(name = "field") - String field; + @Nested + @DisplayName("With @TestBean in enclosing class and in @Nested class") + public class TestBeanFieldInEnclosingClassTests { - @TestBean(name = "methodRenamed1", methodName = "field") - String methodRenamed1; + @TestBean(name = "nestedField") + String nestedField; - static String field() { - return "fieldOverride"; - } + @TestBean(name = "methodRenamed2", methodName = "nestedField") + String methodRenamed2; - static String nestedField() { - return "nestedFieldOverride"; - } @Test void fieldHasOverride(ApplicationContext ctx) { @@ -83,17 +89,21 @@ public class TestBeanByNameLookupTestMethodScopedExtensionContextIntegrationTest assertThat(methodRenamed1).as("injection point").isEqualTo("fieldOverride"); } + @Test + void nestedFieldHasOverride(ApplicationContext ctx) { + assertThat(ctx.getBean("nestedField")).as("applicationContext").isEqualTo("nestedFieldOverride"); + assertThat(nestedField).isEqualTo("nestedFieldOverride"); + } - @Nested - @DisplayName("With @TestBean in enclosing class and in @Nested class") - public class TestBeanFieldInEnclosingClassTestCase { - - @TestBean(name = "nestedField") - String nestedField; - - @TestBean(name = "methodRenamed2", methodName = "nestedField") - String methodRenamed2; + @Test + void nestedFieldWithMethodNameHasOverride(ApplicationContext ctx) { + assertThat(ctx.getBean("methodRenamed2")).as("applicationContext").isEqualTo("nestedFieldOverride"); + assertThat(methodRenamed2).isEqualTo("nestedFieldOverride"); + } + @Nested + @DisplayName("With @TestBean in the enclosing classes") + public class TestBeanFieldInEnclosingClassLevel2Tests { @Test void fieldHasOverride(ApplicationContext ctx) { @@ -118,62 +128,33 @@ public class TestBeanByNameLookupTestMethodScopedExtensionContextIntegrationTest assertThat(ctx.getBean("methodRenamed2")).as("applicationContext").isEqualTo("nestedFieldOverride"); assertThat(methodRenamed2).isEqualTo("nestedFieldOverride"); } + } + } - @Nested - @DisplayName("With @TestBean in the enclosing classes") - public class TestBeanFieldInEnclosingClassLevel2TestCase { - - @Test - void fieldHasOverride(ApplicationContext ctx) { - assertThat(ctx.getBean("field")).as("applicationContext").isEqualTo("fieldOverride"); - assertThat(field).as("injection point").isEqualTo("fieldOverride"); - } - - @Test - void fieldWithMethodNameHasOverride(ApplicationContext ctx) { - assertThat(ctx.getBean("methodRenamed1")).as("applicationContext").isEqualTo("fieldOverride"); - assertThat(methodRenamed1).as("injection point").isEqualTo("fieldOverride"); - } - - @Test - void nestedFieldHasOverride(ApplicationContext ctx) { - assertThat(ctx.getBean("nestedField")).as("applicationContext").isEqualTo("nestedFieldOverride"); - assertThat(nestedField).isEqualTo("nestedFieldOverride"); - } - - @Test - void nestedFieldWithMethodNameHasOverride(ApplicationContext ctx) { - assertThat(ctx.getBean("methodRenamed2")).as("applicationContext").isEqualTo("nestedFieldOverride"); - assertThat(methodRenamed2).isEqualTo("nestedFieldOverride"); - } - } + @Nested + @DisplayName("With factory method in enclosing class") + public class TestBeanFactoryMethodInEnclosingClassTests { + + @TestBean(methodName = "nestedField", name = "nestedField") + String nestedField; + + @Test + void nestedFieldHasOverride(ApplicationContext ctx) { + assertThat(ctx.getBean("nestedField")).as("applicationContext").isEqualTo("nestedFieldOverride"); + assertThat(nestedField).isEqualTo("nestedFieldOverride"); } @Nested - @DisplayName("With factory method in enclosing class") - public class TestBeanFactoryMethodInEnclosingClassTestCase { + @DisplayName("With factory method in the enclosing class of the enclosing class") + public class TestBeanFactoryMethodInEnclosingClassLevel2Tests { - @TestBean(methodName = "nestedField", name = "nestedField") - String nestedField; + @TestBean(methodName = "nestedField", name = "nestedNestedField") + String nestedNestedField; @Test void nestedFieldHasOverride(ApplicationContext ctx) { - assertThat(ctx.getBean("nestedField")).as("applicationContext").isEqualTo("nestedFieldOverride"); - assertThat(nestedField).isEqualTo("nestedFieldOverride"); - } - - @Nested - @DisplayName("With factory method in the enclosing class of the enclosing class") - public class TestBeanFactoryMethodInEnclosingClassLevel2TestCase { - - @TestBean(methodName = "nestedField", name = "nestedNestedField") - String nestedNestedField; - - @Test - void nestedFieldHasOverride(ApplicationContext ctx) { - assertThat(ctx.getBean("nestedNestedField")).as("applicationContext").isEqualTo("nestedFieldOverride"); - assertThat(nestedNestedField).isEqualTo("nestedFieldOverride"); - } + assertThat(ctx.getBean("nestedNestedField")).as("applicationContext").isEqualTo("nestedFieldOverride"); + assertThat(nestedNestedField).isEqualTo("nestedFieldOverride"); } } } diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanByNameLookupTestClassScopedExtensionContextIntegrationTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanByNameLookupTestClassScopedExtensionContextIntegrationTests.java index 0ff4d3d5df8..03345c3c231 100644 --- a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanByNameLookupTestClassScopedExtensionContextIntegrationTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanByNameLookupTestClassScopedExtensionContextIntegrationTests.java @@ -30,6 +30,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; import org.springframework.test.context.bean.override.example.ExampleService; import org.springframework.test.context.bean.override.example.RealExampleService; +import org.springframework.test.context.junit.jupiter.SpringExtensionConfig; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.springframework.test.mockito.MockitoAssertions; @@ -44,6 +45,7 @@ import static org.assertj.core.api.Assertions.assertThat; * @since 6.2 */ @SpringJUnitConfig +@SpringExtensionConfig(useTestClassScopedExtensionContext = true) public class MockitoBeanByNameLookupTestClassScopedExtensionContextIntegrationTests { @MockitoBean("field") diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanByNameLookupTestMethodScopedExtensionContextIntegrationTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanByNameLookupTestMethodScopedExtensionContextIntegrationTests.java index e2c5986d948..70310538847 100644 --- a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanByNameLookupTestMethodScopedExtensionContextIntegrationTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanByNameLookupTestMethodScopedExtensionContextIntegrationTests.java @@ -20,7 +20,6 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope; -import org.junit.platform.testkit.engine.EngineTestKit; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -33,9 +32,6 @@ import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.springframework.test.mockito.MockitoAssertions; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope.DEFAULT_SCOPE_PROPERTY_NAME; -import static org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope.TEST_METHOD; -import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; /** * Integration tests for {@link MockitoBean} that use by-name lookup with @@ -45,27 +41,54 @@ import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass * @author Sam Brannen * @since 6.2.13 */ +@SpringJUnitConfig public class MockitoBeanByNameLookupTestMethodScopedExtensionContextIntegrationTests { + @MockitoBean("field") + ExampleService field; + + @MockitoBean("nonExistingBean") + ExampleService nonExisting; + + @Test - void runTests() { - EngineTestKit.engine("junit-jupiter") - .configurationParameter(DEFAULT_SCOPE_PROPERTY_NAME, TEST_METHOD.name()) - .selectors(selectClass(TestCase.class)) - .execute() - .testEvents() - .assertStatistics(stats -> stats.started(6).succeeded(6).failed(0)); + void fieldAndRenamedFieldHaveSameOverride(ApplicationContext ctx) { + assertThat(ctx.getBean("field")) + .isInstanceOf(ExampleService.class) + .satisfies(MockitoAssertions::assertIsMock) + .isSameAs(field); + + assertThat(field.greeting()).as("mocked greeting").isNull(); } + @Test + void fieldIsMockedWhenNoOriginalBean(ApplicationContext ctx) { + assertThat(ctx.getBean("nonExistingBean")) + .isInstanceOf(ExampleService.class) + .satisfies(MockitoAssertions::assertIsMock) + .isSameAs(nonExisting); + + assertThat(nonExisting.greeting()).as("mocked greeting").isNull(); + } + + + @Nested + @DisplayName("With @MockitoBean in enclosing class and in @Nested class") + public class MockitoBeanNestedTests { - @SpringJUnitConfig - public static class TestCase { + @Autowired + @Qualifier("field") + ExampleService localField; - @MockitoBean("field") - ExampleService field; + @Autowired + @Qualifier("nonExistingBean") + ExampleService localNonExisting; - @MockitoBean("nonExistingBean") - ExampleService nonExisting; + @MockitoBean("nestedField") + ExampleService nestedField; + + @MockitoBean("nestedNonExistingBean") + ExampleService nestedNonExisting; @Test @@ -73,9 +96,9 @@ public class MockitoBeanByNameLookupTestMethodScopedExtensionContextIntegrationT assertThat(ctx.getBean("field")) .isInstanceOf(ExampleService.class) .satisfies(MockitoAssertions::assertIsMock) - .isSameAs(field); + .isSameAs(localField); - assertThat(field.greeting()).as("mocked greeting").isNull(); + assertThat(localField.greeting()).as("mocked greeting").isNull(); } @Test @@ -83,66 +106,25 @@ public class MockitoBeanByNameLookupTestMethodScopedExtensionContextIntegrationT assertThat(ctx.getBean("nonExistingBean")) .isInstanceOf(ExampleService.class) .satisfies(MockitoAssertions::assertIsMock) - .isSameAs(nonExisting); + .isSameAs(localNonExisting); - assertThat(nonExisting.greeting()).as("mocked greeting").isNull(); + assertThat(localNonExisting.greeting()).as("mocked greeting").isNull(); } + @Test + void nestedFieldAndRenamedFieldHaveSameOverride(ApplicationContext ctx) { + assertThat(ctx.getBean("nestedField")) + .isInstanceOf(ExampleService.class) + .satisfies(MockitoAssertions::assertIsMock) + .isSameAs(nestedField); + } - @Nested - @DisplayName("With @MockitoBean in enclosing class and in @Nested class") - public class MockitoBeanNestedTestCase { - - @Autowired - @Qualifier("field") - ExampleService localField; - - @Autowired - @Qualifier("nonExistingBean") - ExampleService localNonExisting; - - @MockitoBean("nestedField") - ExampleService nestedField; - - @MockitoBean("nestedNonExistingBean") - ExampleService nestedNonExisting; - - - @Test - void fieldAndRenamedFieldHaveSameOverride(ApplicationContext ctx) { - assertThat(ctx.getBean("field")) - .isInstanceOf(ExampleService.class) - .satisfies(MockitoAssertions::assertIsMock) - .isSameAs(localField); - - assertThat(localField.greeting()).as("mocked greeting").isNull(); - } - - @Test - void fieldIsMockedWhenNoOriginalBean(ApplicationContext ctx) { - assertThat(ctx.getBean("nonExistingBean")) - .isInstanceOf(ExampleService.class) - .satisfies(MockitoAssertions::assertIsMock) - .isSameAs(localNonExisting); - - assertThat(localNonExisting.greeting()).as("mocked greeting").isNull(); - } - - @Test - void nestedFieldAndRenamedFieldHaveSameOverride(ApplicationContext ctx) { - assertThat(ctx.getBean("nestedField")) - .isInstanceOf(ExampleService.class) - .satisfies(MockitoAssertions::assertIsMock) - .isSameAs(nestedField); - } - - @Test - void nestedFieldIsMockedWhenNoOriginalBean(ApplicationContext ctx) { - assertThat(ctx.getBean("nestedNonExistingBean")) - .isInstanceOf(ExampleService.class) - .satisfies(MockitoAssertions::assertIsMock) - .isSameAs(nestedNonExisting); - } + @Test + void nestedFieldIsMockedWhenNoOriginalBean(ApplicationContext ctx) { + assertThat(ctx.getBean("nestedNonExistingBean")) + .isInstanceOf(ExampleService.class) + .satisfies(MockitoAssertions::assertIsMock) + .isSameAs(nestedNonExisting); } } diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanByNameLookupTestClassScopedExtensionContextIntegrationTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanByNameLookupTestClassScopedExtensionContextIntegrationTests.java index 49dc19acab2..6924ba66a5e 100644 --- a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanByNameLookupTestClassScopedExtensionContextIntegrationTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanByNameLookupTestClassScopedExtensionContextIntegrationTests.java @@ -30,7 +30,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Scope; import org.springframework.test.context.bean.override.example.ExampleService; import org.springframework.test.context.bean.override.example.RealExampleService; -import org.springframework.test.context.bean.override.mockito.MockitoSpyBeanByNameLookupTestClassScopedExtensionContextIntegrationTests.Config; +import org.springframework.test.context.junit.jupiter.SpringExtensionConfig; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.springframework.test.mockito.MockitoAssertions; @@ -44,7 +44,8 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Sam Brannen * @since 6.2 */ -@SpringJUnitConfig(Config.class) +@SpringJUnitConfig +@SpringExtensionConfig(useTestClassScopedExtensionContext = true) public class MockitoSpyBeanByNameLookupTestClassScopedExtensionContextIntegrationTests { @MockitoSpyBean("field1") diff --git a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanByNameLookupTestMethodScopedExtensionContextIntegrationTests.java b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanByNameLookupTestMethodScopedExtensionContextIntegrationTests.java index 6aa660a9f5f..6e8e35d195a 100644 --- a/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanByNameLookupTestMethodScopedExtensionContextIntegrationTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanByNameLookupTestMethodScopedExtensionContextIntegrationTests.java @@ -20,7 +20,6 @@ import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope; -import org.junit.platform.testkit.engine.EngineTestKit; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -33,9 +32,6 @@ import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.springframework.test.mockito.MockitoAssertions; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope.DEFAULT_SCOPE_PROPERTY_NAME; -import static org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope.TEST_METHOD; -import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; /** * Integration tests for {@link MockitoSpyBean} that use by-name lookup with @@ -45,70 +41,57 @@ import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass * @author Sam Brannen * @since 6.2.13 */ +@SpringJUnitConfig public class MockitoSpyBeanByNameLookupTestMethodScopedExtensionContextIntegrationTests { + @MockitoSpyBean("field1") + ExampleService field; + + @Test - void runTests() { - EngineTestKit.engine("junit-jupiter") - .configurationParameter(DEFAULT_SCOPE_PROPERTY_NAME, TEST_METHOD.name()) - .selectors(selectClass(TestCase.class)) - .execute() - .testEvents() - .assertStatistics(stats -> stats.started(3).succeeded(3).failed(0)); + void fieldHasOverride(ApplicationContext ctx) { + assertThat(ctx.getBean("field1")) + .isInstanceOf(ExampleService.class) + .satisfies(MockitoAssertions::assertIsSpy) + .isSameAs(field); + + assertThat(field.greeting()).isEqualTo("bean1"); } - @SpringJUnitConfig(Config.class) - public static class TestCase { + @Nested + @DisplayName("With @MockitoSpyBean in enclosing class and in @Nested class") + public class MockitoSpyBeanNestedTests { - @MockitoSpyBean("field1") - ExampleService field; + @Autowired + @Qualifier("field1") + ExampleService localField; + @MockitoSpyBean("field2") + ExampleService nestedField; @Test void fieldHasOverride(ApplicationContext ctx) { assertThat(ctx.getBean("field1")) .isInstanceOf(ExampleService.class) .satisfies(MockitoAssertions::assertIsSpy) - .isSameAs(field); + .isSameAs(localField); - assertThat(field.greeting()).isEqualTo("bean1"); + assertThat(localField.greeting()).isEqualTo("bean1"); } + @Test + void nestedFieldHasOverride(ApplicationContext ctx) { + assertThat(ctx.getBean("field2")) + .isInstanceOf(ExampleService.class) + .satisfies(MockitoAssertions::assertIsSpy) + .isSameAs(nestedField); - @Nested - @DisplayName("With @MockitoSpyBean in enclosing class and in @Nested class") - public class MockitoSpyBeanNestedTestCase { - - @Autowired - @Qualifier("field1") - ExampleService localField; - - @MockitoSpyBean("field2") - ExampleService nestedField; - - @Test - void fieldHasOverride(ApplicationContext ctx) { - assertThat(ctx.getBean("field1")) - .isInstanceOf(ExampleService.class) - .satisfies(MockitoAssertions::assertIsSpy) - .isSameAs(localField); - - assertThat(localField.greeting()).isEqualTo("bean1"); - } - - @Test - void nestedFieldHasOverride(ApplicationContext ctx) { - assertThat(ctx.getBean("field2")) - .isInstanceOf(ExampleService.class) - .satisfies(MockitoAssertions::assertIsSpy) - .isSameAs(nestedField); - - assertThat(nestedField.greeting()).isEqualTo("bean2"); - } + assertThat(nestedField.greeting()).isEqualTo("bean2"); } } + @Configuration(proxyBeanMethods = false) static class Config { diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ActiveProfilesTestClassScopedExtensionContextNestedTests.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ActiveProfilesTestClassScopedExtensionContextNestedTests.java index ce83b45a1f5..c106a554701 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ActiveProfilesTestClassScopedExtensionContextNestedTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ActiveProfilesTestClassScopedExtensionContextNestedTests.java @@ -30,6 +30,7 @@ import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.NestedTestConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.context.junit.jupiter.SpringExtensionConfig; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.springframework.test.context.junit.jupiter.nested.ActiveProfilesTestClassScopedExtensionContextNestedTests.Config1; @@ -47,6 +48,7 @@ import static org.springframework.test.context.NestedTestConfiguration.Enclosing * @since 5.3 */ @SpringJUnitConfig(Config1.class) +@SpringExtensionConfig(useTestClassScopedExtensionContext = true) @ActiveProfiles("1") @NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default class ActiveProfilesTestClassScopedExtensionContextNestedTests { diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ActiveProfilesTestMethodScopedExtensionContextNestedTests.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ActiveProfilesTestMethodScopedExtensionContextNestedTests.java index a8a73be4183..cff8e4072d5 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ActiveProfilesTestMethodScopedExtensionContextNestedTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ActiveProfilesTestMethodScopedExtensionContextNestedTests.java @@ -21,7 +21,6 @@ import java.util.List; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope; -import org.junit.platform.testkit.engine.EngineTestKit; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; @@ -32,11 +31,9 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.NestedTestConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import org.springframework.test.context.junit.jupiter.nested.ActiveProfilesTestMethodScopedExtensionContextNestedTests.Config1; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope.DEFAULT_SCOPE_PROPERTY_NAME; -import static org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope.TEST_METHOD; -import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.INHERIT; import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.OVERRIDE; @@ -49,72 +46,77 @@ import static org.springframework.test.context.NestedTestConfiguration.Enclosing * @author Sam Brannen * @since 6.2.13 */ +@SpringJUnitConfig(Config1.class) +@ActiveProfiles("1") +@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default class ActiveProfilesTestMethodScopedExtensionContextNestedTests { + @Autowired + List strings; + + @Test - void runTests() { - EngineTestKit.engine("junit-jupiter") - .configurationParameter(DEFAULT_SCOPE_PROPERTY_NAME, TEST_METHOD.name()) - .selectors(selectClass(TestCase.class)) - .execute() - .testEvents() - .assertStatistics(stats -> stats.started(7).succeeded(7).failed(0)); + void test() { + assertThat(this.strings).containsExactlyInAnyOrder("X", "A1"); } - @SpringJUnitConfig(Config1.class) - @ActiveProfiles("1") - @NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default - static class TestCase { + @Nested + @NestedTestConfiguration(INHERIT) + class InheritedConfigTests { @Autowired - List strings; + List localStrings; @Test void test() { - assertThat(this.strings).containsExactlyInAnyOrder("X", "A1"); + assertThat(strings) + .isEqualTo(this.localStrings) + .containsExactlyInAnyOrder("X", "A1"); } + } + @Nested + @SpringJUnitConfig(Config2.class) + @ActiveProfiles("2") + class ConfigOverriddenByDefaultTests { - @Nested - @NestedTestConfiguration(INHERIT) - class InheritedConfigTestCase { - - @Autowired - List localStrings; + @Autowired + List localStrings; - @Test - void test() { - assertThat(strings) - .isEqualTo(this.localStrings) - .containsExactlyInAnyOrder("X", "A1"); - } + @Test + void test() { + assertThat(strings) + .isEqualTo(this.localStrings) + .containsExactlyInAnyOrder("Y", "A2"); } + } - @Nested - @SpringJUnitConfig(Config2.class) - @ActiveProfiles("2") - class ConfigOverriddenByDefaultTestCase { + @Nested + @NestedTestConfiguration(INHERIT) + @ContextConfiguration(classes = Config2.class) + @ActiveProfiles("2") + class InheritedAndExtendedConfigTests { - @Autowired - List localStrings; + @Autowired + List localStrings; - @Test - void test() { - assertThat(strings) - .isEqualTo(this.localStrings) - .containsExactlyInAnyOrder("Y", "A2"); - } + @Test + void test() { + assertThat(strings) + .isEqualTo(this.localStrings) + .containsExactlyInAnyOrder("X", "A1", "Y", "A2"); } + @Nested - @NestedTestConfiguration(INHERIT) - @ContextConfiguration(classes = Config2.class) - @ActiveProfiles("2") - class InheritedAndExtendedConfigTestCase { + @NestedTestConfiguration(OVERRIDE) + @SpringJUnitConfig({ Config1.class, Config2.class, Config3.class }) + @ActiveProfiles("3") + class DoubleNestedWithOverriddenConfigTests { @Autowired List localStrings; @@ -124,15 +126,14 @@ class ActiveProfilesTestMethodScopedExtensionContextNestedTests { void test() { assertThat(strings) .isEqualTo(this.localStrings) - .containsExactlyInAnyOrder("X", "A1", "Y", "A2"); + .containsExactlyInAnyOrder("X", "Y", "Z", "A3"); } @Nested - @NestedTestConfiguration(OVERRIDE) - @SpringJUnitConfig({ Config1.class, Config2.class, Config3.class }) - @ActiveProfiles("3") - class DoubleNestedWithOverriddenConfigTestCase { + @NestedTestConfiguration(INHERIT) + @ActiveProfiles(profiles = "2", inheritProfiles = false) + class TripleNestedWithInheritedConfigButOverriddenProfilesTests { @Autowired List localStrings; @@ -142,41 +143,23 @@ class ActiveProfilesTestMethodScopedExtensionContextNestedTests { void test() { assertThat(strings) .isEqualTo(this.localStrings) - .containsExactlyInAnyOrder("X", "Y", "Z", "A3"); - } - - - @Nested - @NestedTestConfiguration(INHERIT) - @ActiveProfiles(profiles = "2", inheritProfiles = false) - class TripleNestedWithInheritedConfigButOverriddenProfilesTestCase { - - @Autowired - List localStrings; - - - @Test - void test() { - assertThat(strings) - .isEqualTo(this.localStrings) - .containsExactlyInAnyOrder("X", "Y", "Z", "A2"); - } + .containsExactlyInAnyOrder("X", "Y", "Z", "A2"); } + } - @Nested - @NestedTestConfiguration(INHERIT) - class TripleNestedWithInheritedConfigAndTestInterfaceTestCase implements TestInterface { + @Nested + @NestedTestConfiguration(INHERIT) + class TripleNestedWithInheritedConfigAndTestInterfaceTests implements TestInterface { - @Autowired - List localStrings; + @Autowired + List localStrings; - @Test - void test() { - assertThat(strings) - .isEqualTo(this.localStrings) - .containsExactlyInAnyOrder("X", "Y", "Z", "A2", "A3"); - } + @Test + void test() { + assertThat(strings) + .isEqualTo(this.localStrings) + .containsExactlyInAnyOrder("X", "Y", "Z", "A2", "A3"); } } } diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ConstructorInjectionTestClassScopedExtensionContextNestedTests.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ConstructorInjectionTestClassScopedExtensionContextNestedTests.java index 81cf6117107..fbd29e7553d 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ConstructorInjectionTestClassScopedExtensionContextNestedTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ConstructorInjectionTestClassScopedExtensionContextNestedTests.java @@ -28,6 +28,7 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.test.context.NestedTestConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.context.junit.jupiter.SpringExtensionConfig; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.springframework.test.context.junit.jupiter.nested.ConstructorInjectionTestClassScopedExtensionContextNestedTests.TopLevelConfig; @@ -46,6 +47,7 @@ import static org.springframework.test.context.NestedTestConfiguration.Enclosing * @see org.springframework.test.context.junit4.nested.NestedTestsWithSpringRulesTests */ @SpringJUnitConfig(TopLevelConfig.class) +@SpringExtensionConfig(useTestClassScopedExtensionContext = true) @NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default class ConstructorInjectionTestClassScopedExtensionContextNestedTests { diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ConstructorInjectionTestMethodScopedExtensionContextNestedTests.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ConstructorInjectionTestMethodScopedExtensionContextNestedTests.java index b6ba04cd91a..5882ed52867 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ConstructorInjectionTestMethodScopedExtensionContextNestedTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ConstructorInjectionTestMethodScopedExtensionContextNestedTests.java @@ -20,7 +20,6 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope; -import org.junit.platform.testkit.engine.EngineTestKit; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -30,11 +29,9 @@ import org.springframework.context.annotation.Configuration; import org.springframework.test.context.NestedTestConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import org.springframework.test.context.junit.jupiter.nested.ConstructorInjectionTestMethodScopedExtensionContextNestedTests.TopLevelConfig; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope.DEFAULT_SCOPE_PROPERTY_NAME; -import static org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope.TEST_METHOD; -import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.OVERRIDE; /** @@ -48,106 +45,91 @@ import static org.springframework.test.context.NestedTestConfiguration.Enclosing * @see ContextConfigurationTestClassScopedExtensionContextNestedTests * @see org.springframework.test.context.junit4.nested.NestedTestsWithSpringRulesTests */ +@SpringJUnitConfig(TopLevelConfig.class) +@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default class ConstructorInjectionTestMethodScopedExtensionContextNestedTests { - @Test - void runTests() { - EngineTestKit.engine("junit-jupiter") - .configurationParameter(DEFAULT_SCOPE_PROPERTY_NAME, TEST_METHOD.name()) - .selectors(selectClass(TestCase.class)) - .execute() - .testEvents() - .assertStatistics(stats -> stats.started(5).succeeded(5).failed(0)); + final String foo; + + ConstructorInjectionTestMethodScopedExtensionContextNestedTests(TestInfo testInfo, @Autowired String foo) { + this.foo = foo; } + @Test + void topLevelTest() { + assertThat(foo).isEqualTo("foo"); + } - @SpringJUnitConfig(TopLevelConfig.class) - @NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default - static class TestCase { + @Nested + @SpringJUnitConfig(NestedConfig.class) + class AutowiredConstructorTests { - final String foo; + final String bar; - TestCase(TestInfo testInfo, @Autowired String foo) { - this.foo = foo; + @Autowired + AutowiredConstructorTests(String bar) { + this.bar = bar; } @Test - void topLevelTest() { - assertThat(foo).isEqualTo("foo"); + void nestedTest() { + assertThat(foo).isEqualTo("bar"); + assertThat(bar).isEqualTo("bar"); } + } - @Nested - @SpringJUnitConfig(NestedConfig.class) - class AutowiredConstructorTestCase { - - final String bar; + @Nested + @SpringJUnitConfig(NestedConfig.class) + class AutowiredConstructorParameterTests { - @Autowired - AutowiredConstructorTestCase(String bar) { - this.bar = bar; - } + final String bar; - @Test - void nestedTest() { - assertThat(foo).isEqualTo("bar"); - assertThat(bar).isEqualTo("bar"); - } + AutowiredConstructorParameterTests(@Autowired String bar) { + this.bar = bar; } - @Nested - @SpringJUnitConfig(NestedConfig.class) - class AutowiredConstructorParameterTestCase { - - final String bar; - - AutowiredConstructorParameterTestCase(@Autowired String bar) { - this.bar = bar; - } - - @Test - void nestedTest() { - assertThat(foo).isEqualTo("bar"); - assertThat(bar).isEqualTo("bar"); - } + @Test + void nestedTest() { + assertThat(foo).isEqualTo("bar"); + assertThat(bar).isEqualTo("bar"); } + } - @Nested - @SpringJUnitConfig(NestedConfig.class) - class QualifiedConstructorParameterTestCase { - - final String bar; + @Nested + @SpringJUnitConfig(NestedConfig.class) + class QualifiedConstructorParameterTests { - QualifiedConstructorParameterTestCase(TestInfo testInfo, @Qualifier("bar") String s) { - this.bar = s; - } + final String bar; - @Test - void nestedTest() { - assertThat(foo).isEqualTo("bar"); - assertThat(bar).isEqualTo("bar"); - } + QualifiedConstructorParameterTests(TestInfo testInfo, @Qualifier("bar") String s) { + this.bar = s; } - @Nested - @SpringJUnitConfig(NestedConfig.class) - class SpelConstructorParameterTestCase { + @Test + void nestedTest() { + assertThat(foo).isEqualTo("bar"); + assertThat(bar).isEqualTo("bar"); + } + } - final String bar; - final int answer; + @Nested + @SpringJUnitConfig(NestedConfig.class) + class SpelConstructorParameterTests { - SpelConstructorParameterTestCase(@Autowired String bar, TestInfo testInfo, @Value("#{ 6 * 7 }") int answer) { - this.bar = bar; - this.answer = answer; - } + final String bar; + final int answer; - @Test - void nestedTest() { - assertThat(foo).isEqualTo("bar"); - assertThat(bar).isEqualTo("bar"); - assertThat(answer).isEqualTo(42); - } + SpelConstructorParameterTests(@Autowired String bar, TestInfo testInfo, @Value("#{ 6 * 7 }") int answer) { + this.bar = bar; + this.answer = answer; } + @Test + void nestedTest() { + assertThat(foo).isEqualTo("bar"); + assertThat(bar).isEqualTo("bar"); + assertThat(answer).isEqualTo(42); + } } // ------------------------------------------------------------------------- diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextConfigurationTestClassScopedExtensionContextNestedTests.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextConfigurationTestClassScopedExtensionContextNestedTests.java index 34bbcc3bec6..607a2190fcc 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextConfigurationTestClassScopedExtensionContextNestedTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextConfigurationTestClassScopedExtensionContextNestedTests.java @@ -27,6 +27,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.NestedTestConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.context.junit.jupiter.SpringExtensionConfig; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.springframework.test.context.junit.jupiter.nested.ContextConfigurationTestClassScopedExtensionContextNestedTests.TopLevelConfig; @@ -46,6 +47,7 @@ import static org.springframework.test.context.NestedTestConfiguration.Enclosing * @see org.springframework.test.context.junit4.nested.NestedTestsWithSpringRulesTests */ @SpringJUnitConfig(TopLevelConfig.class) +@SpringExtensionConfig(useTestClassScopedExtensionContext = true) @NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default class ContextConfigurationTestClassScopedExtensionContextNestedTests { diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextConfigurationTestMethodScopedExtensionContextNestedTests.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextConfigurationTestMethodScopedExtensionContextNestedTests.java index fecf82498ab..2d1a35b02c6 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextConfigurationTestMethodScopedExtensionContextNestedTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextConfigurationTestMethodScopedExtensionContextNestedTests.java @@ -19,7 +19,6 @@ package org.springframework.test.context.junit.jupiter.nested; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope; -import org.junit.platform.testkit.engine.EngineTestKit; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -29,11 +28,9 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.NestedTestConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import org.springframework.test.context.junit.jupiter.nested.ContextConfigurationTestMethodScopedExtensionContextNestedTests.TopLevelConfig; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope.DEFAULT_SCOPE_PROPERTY_NAME; -import static org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope.TEST_METHOD; -import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.INHERIT; import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.OVERRIDE; @@ -48,46 +45,72 @@ import static org.springframework.test.context.NestedTestConfiguration.Enclosing * @see ConstructorInjectionTestClassScopedExtensionContextNestedTests * @see org.springframework.test.context.junit4.nested.NestedTestsWithSpringRulesTests */ +@SpringJUnitConfig(TopLevelConfig.class) +@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default class ContextConfigurationTestMethodScopedExtensionContextNestedTests { private static final String FOO = "foo"; private static final String BAR = "bar"; private static final String BAZ = "baz"; + @Autowired(required = false) + @Qualifier("foo") + String foo; + @Test - void runTests() { - EngineTestKit.engine("junit-jupiter") - .configurationParameter(DEFAULT_SCOPE_PROPERTY_NAME, TEST_METHOD.name()) - .selectors(selectClass(TestCase.class)) - .execute() - .testEvents() - .assertStatistics(stats -> stats.started(6).succeeded(6).failed(0)); + void topLevelTest() { + assertThat(foo).isEqualTo(FOO); } - @SpringJUnitConfig(TopLevelConfig.class) - @NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default - static class TestCase { + @Nested + @SpringJUnitConfig(NestedConfig.class) + class NestedTests { + + @Autowired(required = false) + @Qualifier("foo") + String localFoo; + + @Autowired + String bar; + - private static final String FOO = "foo"; - private static final String BAR = "bar"; - private static final String BAZ = "baz"; + @Test + void test() { + assertThat(foo).as("foo bean should not be present").isNull(); + assertThat(this.localFoo).as("local foo bean should not be present").isNull(); + assertThat(this.bar).isEqualTo(BAR); + } + } + + @Nested + @NestedTestConfiguration(INHERIT) + class NestedTestsWithInheritedConfigTests { @Autowired(required = false) @Qualifier("foo") - String foo; + String localFoo; + + @Autowired + String bar; @Test - void topLevelTest() { + void test() { + // Since the configuration is inherited, the foo field in the outer instance + // and the bar field in the inner instance should both have been injected + // from the test ApplicationContext for the outer instance. assertThat(foo).isEqualTo(FOO); + assertThat(this.localFoo).isEqualTo(FOO); + assertThat(this.bar).isEqualTo(FOO); } @Nested + @NestedTestConfiguration(OVERRIDE) @SpringJUnitConfig(NestedConfig.class) - class NestedTestCase { + class DoubleNestedWithOverriddenConfigTests { @Autowired(required = false) @Qualifier("foo") @@ -103,35 +126,11 @@ class ContextConfigurationTestMethodScopedExtensionContextNestedTests { assertThat(this.localFoo).as("local foo bean should not be present").isNull(); assertThat(this.bar).isEqualTo(BAR); } - } - - @Nested - @NestedTestConfiguration(INHERIT) - class NestedTestCaseWithInheritedConfigTestCase { - - @Autowired(required = false) - @Qualifier("foo") - String localFoo; - - @Autowired - String bar; - - - @Test - void test() { - // Since the configuration is inherited, the foo field in the outer instance - // and the bar field in the inner instance should both have been injected - // from the test ApplicationContext for the outer instance. - assertThat(foo).isEqualTo(FOO); - assertThat(this.localFoo).isEqualTo(FOO); - assertThat(this.bar).isEqualTo(FOO); - } @Nested - @NestedTestConfiguration(OVERRIDE) - @SpringJUnitConfig(NestedConfig.class) - class DoubleNestedWithOverriddenConfigTestCase { + @NestedTestConfiguration(INHERIT) + class TripleNestedWithInheritedConfigTests { @Autowired(required = false) @Qualifier("foo") @@ -147,55 +146,33 @@ class ContextConfigurationTestMethodScopedExtensionContextNestedTests { assertThat(this.localFoo).as("local foo bean should not be present").isNull(); assertThat(this.bar).isEqualTo(BAR); } + } + @Nested + @NestedTestConfiguration(INHERIT) + class TripleNestedWithInheritedConfigAndTestInterfaceTests implements TestInterface { - @Nested - @NestedTestConfiguration(INHERIT) - class TripleNestedWithInheritedConfigTestCase { - - @Autowired(required = false) - @Qualifier("foo") - String localFoo; - - @Autowired - String bar; - - - @Test - void test() { - assertThat(foo).as("foo bean should not be present").isNull(); - assertThat(this.localFoo).as("local foo bean should not be present").isNull(); - assertThat(this.bar).isEqualTo(BAR); - } - } - - @Nested - @NestedTestConfiguration(INHERIT) - class TripleNestedWithInheritedConfigAndTestInterfaceTestCase implements TestInterface { - - @Autowired(required = false) - @Qualifier("foo") - String localFoo; + @Autowired(required = false) + @Qualifier("foo") + String localFoo; - @Autowired - @Qualifier("bar") - String bar; + @Autowired + @Qualifier("bar") + String bar; - @Autowired - String baz; + @Autowired + String baz; - @Test - void test() { - assertThat(foo).as("foo bean should not be present").isNull(); - assertThat(this.localFoo).as("local foo bean should not be present").isNull(); - assertThat(this.bar).isEqualTo(BAR); - assertThat(this.baz).isEqualTo(BAZ); - } + @Test + void test() { + assertThat(foo).as("foo bean should not be present").isNull(); + assertThat(this.localFoo).as("local foo bean should not be present").isNull(); + assertThat(this.bar).isEqualTo(BAR); + assertThat(this.baz).isEqualTo(BAZ); } } } - } // ------------------------------------------------------------------------- diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextHierarchyTestClassScopedExtensionContextNestedTests.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextHierarchyTestClassScopedExtensionContextNestedTests.java index c47cf2a630b..399b09584b2 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextHierarchyTestClassScopedExtensionContextNestedTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextHierarchyTestClassScopedExtensionContextNestedTests.java @@ -31,6 +31,7 @@ import org.springframework.test.context.ContextHierarchy; import org.springframework.test.context.NestedTestConfiguration; import org.springframework.test.context.aot.DisabledInAotMode; import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.context.junit.jupiter.SpringExtensionConfig; import org.springframework.test.context.junit.jupiter.nested.ContextHierarchyTestClassScopedExtensionContextNestedTests.ParentConfig; import static org.assertj.core.api.Assertions.assertThat; @@ -47,6 +48,7 @@ import static org.springframework.test.context.NestedTestConfiguration.Enclosing * @since 5.3 */ @ExtendWith(SpringExtension.class) +@SpringExtensionConfig(useTestClassScopedExtensionContext = true) @ContextHierarchy(@ContextConfiguration(classes = ParentConfig.class)) @NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default @DisabledInAotMode("@ContextHierarchy is not supported in AOT") diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextHierarchyTestMethodScopedExtensionContextNestedTests.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextHierarchyTestMethodScopedExtensionContextNestedTests.java index dfc0777c33d..1efd1b4812c 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextHierarchyTestMethodScopedExtensionContextNestedTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextHierarchyTestMethodScopedExtensionContextNestedTests.java @@ -20,7 +20,6 @@ import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope; -import org.junit.platform.testkit.engine.EngineTestKit; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; @@ -32,11 +31,9 @@ import org.springframework.test.context.ContextHierarchy; import org.springframework.test.context.NestedTestConfiguration; import org.springframework.test.context.aot.DisabledInAotMode; import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.context.junit.jupiter.nested.ContextHierarchyTestMethodScopedExtensionContextNestedTests.ParentConfig; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope.DEFAULT_SCOPE_PROPERTY_NAME; -import static org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope.TEST_METHOD; -import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.INHERIT; import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.OVERRIDE; @@ -49,6 +46,10 @@ import static org.springframework.test.context.NestedTestConfiguration.Enclosing * @author Sam Brannen * @since 6.2.13 */ +@ExtendWith(SpringExtension.class) +@ContextHierarchy(@ContextConfiguration(classes = ParentConfig.class)) +@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default +@DisabledInAotMode("@ContextHierarchy is not supported in AOT") class ContextHierarchyTestMethodScopedExtensionContextNestedTests { private static final String FOO = "foo"; @@ -57,65 +58,77 @@ class ContextHierarchyTestMethodScopedExtensionContextNestedTests { private static final String QUX = "qux"; + @Autowired + String foo; + + @Autowired + ApplicationContext context; + + @Test - void runTests() { - EngineTestKit.engine("junit-jupiter") - .configurationParameter(DEFAULT_SCOPE_PROPERTY_NAME, TEST_METHOD.name()) - .selectors(selectClass(TestCase.class)) - .execute() - .testEvents() - .assertStatistics(stats -> stats.started(5).succeeded(5).failed(0)); - } + void topLevelTest() { + assertThat(this.context).as("local ApplicationContext").isNotNull(); + assertThat(this.context.getParent()).as("parent ApplicationContext").isNull(); + assertThat(foo).isEqualTo(FOO); + } - @ExtendWith(SpringExtension.class) - @ContextHierarchy(@ContextConfiguration(classes = ParentConfig.class)) - @NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default - @DisabledInAotMode("@ContextHierarchy is not supported in AOT") - static class TestCase { + @Nested + @ContextConfiguration(classes = NestedConfig.class) + class NestedTests { @Autowired - String foo; + String bar; @Autowired ApplicationContext context; @Test - void topLevelTest() { + void nestedTest() { assertThat(this.context).as("local ApplicationContext").isNotNull(); assertThat(this.context.getParent()).as("parent ApplicationContext").isNull(); - assertThat(foo).isEqualTo(FOO); + // The foo field in the outer instance should have been injected from + // the test ApplicationContext for NestedTests. + assertThat(foo).isEqualTo(BAR); + assertThat(this.bar).isEqualTo(BAR); } + } - @Nested - @ContextConfiguration(classes = NestedConfig.class) - class NestedTestCase { - - @Autowired - String bar; + @Nested + @NestedTestConfiguration(INHERIT) + @ContextConfiguration(classes = Child1Config.class) + class NestedInheritedCfgTests { - @Autowired - ApplicationContext context; + @Autowired + String bar; + @Autowired + ApplicationContext context; - @Test - void nestedTest() { - assertThat(this.context).as("local ApplicationContext").isNotNull(); - assertThat(this.context.getParent()).as("parent ApplicationContext").isNull(); - // The foo field in the outer instance should have been injected from - // the test ApplicationContext for NestedTestCase. - assertThat(foo).isEqualTo(BAR); - assertThat(this.bar).isEqualTo(BAR); - } + @Test + void nestedTest() { + assertThat(this.context).as("local ApplicationContext").isNotNull(); + assertThat(this.context.getParent()).as("parent ApplicationContext").isNotNull(); + + // The foo field in the outer instance and the bar field in the inner + // instance should both have been injected from the test ApplicationContext + // for the inner instance. + assertThat(foo).as("foo") + .isEqualTo(this.context.getBean("foo", String.class)) + .isEqualTo(QUX + 1); + assertThat(this.bar).isEqualTo(BAZ + 1); } @Nested - @NestedTestConfiguration(INHERIT) - @ContextConfiguration(classes = Child1Config.class) - class NestedInheritedCfgTestCase { + @NestedTestConfiguration(OVERRIDE) + @ContextHierarchy({ + @ContextConfiguration(classes = ParentConfig.class), + @ContextConfiguration(classes = Child2Config.class) + }) + class DoubleNestedOverriddenCfgTests { @Autowired String bar; @@ -129,22 +142,19 @@ class ContextHierarchyTestMethodScopedExtensionContextNestedTests { assertThat(this.context).as("local ApplicationContext").isNotNull(); assertThat(this.context.getParent()).as("parent ApplicationContext").isNotNull(); - // The foo field in the outer instance and the bar field in the inner - // instance should both have been injected from the test ApplicationContext - // for the inner instance. assertThat(foo).as("foo") .isEqualTo(this.context.getBean("foo", String.class)) - .isEqualTo(QUX + 1); - assertThat(this.bar).isEqualTo(BAZ + 1); + .isEqualTo(QUX + 2); + assertThat(this.bar).isEqualTo(BAZ + 2); } @Nested - @NestedTestConfiguration(OVERRIDE) - @ContextHierarchy({ - @ContextConfiguration(classes = ParentConfig.class), - @ContextConfiguration(classes = Child2Config.class) - }) - class DoubleNestedOverriddenCfgTestCase { + @NestedTestConfiguration(INHERIT) + class TripleNestedInheritedCfgAndTestInterfaceTests implements TestInterface { + + @Autowired + @Qualifier("foo") + String localFoo; @Autowired String bar; @@ -157,44 +167,16 @@ class ContextHierarchyTestMethodScopedExtensionContextNestedTests { void nestedTest() { assertThat(this.context).as("local ApplicationContext").isNotNull(); assertThat(this.context.getParent()).as("parent ApplicationContext").isNotNull(); + assertThat(this.context.getParent().getParent()).as("grandparent ApplicationContext").isNotNull(); assertThat(foo).as("foo") + .isEqualTo(this.localFoo) .isEqualTo(this.context.getBean("foo", String.class)) - .isEqualTo(QUX + 2); + .isEqualTo("test interface"); assertThat(this.bar).isEqualTo(BAZ + 2); } - - @Nested - @NestedTestConfiguration(INHERIT) - class TripleNestedInheritedCfgAndTestInterfaceTestCase implements TestInterface { - - @Autowired - @Qualifier("foo") - String localFoo; - - @Autowired - String bar; - - @Autowired - ApplicationContext context; - - - @Test - void nestedTest() { - assertThat(this.context).as("local ApplicationContext").isNotNull(); - assertThat(this.context.getParent()).as("parent ApplicationContext").isNotNull(); - assertThat(this.context.getParent().getParent()).as("grandparent ApplicationContext").isNotNull(); - - assertThat(foo).as("foo") - .isEqualTo(this.localFoo) - .isEqualTo(this.context.getBean("foo", String.class)) - .isEqualTo("test interface"); - assertThat(this.bar).isEqualTo(BAZ + 2); - } - } } } - } // ------------------------------------------------------------------------- diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ParameterizedConstructorInjectionTestClassScopedExtensionContextNestedTests.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ParameterizedConstructorInjectionTestClassScopedExtensionContextNestedTests.java new file mode 100644 index 00000000000..8dafbb24832 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ParameterizedConstructorInjectionTestClassScopedExtensionContextNestedTests.java @@ -0,0 +1,186 @@ +/* + * Copyright 2002-present 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 + * + * https://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.test.context.junit.jupiter.nested; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInfo; +import org.junit.jupiter.params.ParameterizedClass; +import org.junit.jupiter.params.provider.ValueSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.NestedTestConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtensionConfig; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import org.springframework.test.context.junit.jupiter.nested.ParameterizedConstructorInjectionTestClassScopedExtensionContextNestedTests.TopLevelConfig; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.OVERRIDE; + +/** + * Parameterized variant of {@link ConstructorInjectionTestClassScopedExtensionContextNestedTests} + * which tests {@link ParameterizedClass @ParameterizedClass} support. + * + * @author Sam Brannen + * @since 7.0 + */ +@SpringJUnitConfig(TopLevelConfig.class) +@SpringExtensionConfig(useTestClassScopedExtensionContext = true) +@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default +@ParameterizedClass +@ValueSource(strings = {"foo", "bar"}) +class ParameterizedConstructorInjectionTestClassScopedExtensionContextNestedTests { + + final String beanName; + final String foo; + final ApplicationContext context; + + + ParameterizedConstructorInjectionTestClassScopedExtensionContextNestedTests( + String beanName, TestInfo testInfo, @Autowired String foo, ApplicationContext context) { + + this.context = context; + this.beanName = beanName; + this.foo = foo; + } + + + @Test + void topLevelTest() { + assertThat(foo).isEqualTo("foo"); + if (beanName.equals("foo")) { + assertThat(context.getBean(beanName, String.class)).isEqualTo(beanName); + } + } + + @Nested + @SpringJUnitConfig(NestedConfig.class) + class AutowiredConstructorTests { + + final String bar; + final ApplicationContext localContext; + + @Autowired + AutowiredConstructorTests(String bar, ApplicationContext context) { + this.bar = bar; + this.localContext = context; + } + + @Test + void nestedTest() { + assertThat(foo).isEqualTo("foo"); + assertThat(bar).isEqualTo("bar"); + if (beanName.equals("bar")) { + assertThat(localContext.getBean(beanName, String.class)).isEqualTo(beanName); + } + } + } + + @Nested + @SpringJUnitConfig(NestedConfig.class) + class AutowiredConstructorParameterTests { + + final String bar; + final ApplicationContext localContext; + + AutowiredConstructorParameterTests(@Autowired String bar, ApplicationContext context) { + this.bar = bar; + this.localContext = context; + } + + @Test + void nestedTest() { + assertThat(foo).isEqualTo("foo"); + assertThat(bar).isEqualTo("bar"); + if (beanName.equals("bar")) { + assertThat(localContext.getBean(beanName, String.class)).isEqualTo(beanName); + } + } + } + + @Nested + @SpringJUnitConfig(NestedConfig.class) + class QualifiedConstructorParameterTests { + + final String bar; + final ApplicationContext localContext; + + QualifiedConstructorParameterTests(TestInfo testInfo, @Qualifier("bar") String s, ApplicationContext context) { + this.bar = s; + this.localContext = context; + } + + @Test + void nestedTest() { + assertThat(foo).isEqualTo("foo"); + assertThat(bar).isEqualTo("bar"); + if (beanName.equals("bar")) { + assertThat(localContext.getBean(beanName, String.class)).isEqualTo(beanName); + } + } + } + + @Nested + @SpringJUnitConfig(NestedConfig.class) + class SpelConstructorParameterTests { + + final String bar; + final int answer; + final ApplicationContext localContext; + + SpelConstructorParameterTests(@Autowired String bar, TestInfo testInfo, @Value("#{ 6 * 7 }") int answer, ApplicationContext context) { + this.bar = bar; + this.answer = answer; + this.localContext = context; + } + + @Test + void nestedTest() { + assertThat(foo).isEqualTo("foo"); + assertThat(bar).isEqualTo("bar"); + assertThat(answer).isEqualTo(42); + if (beanName.equals("bar")) { + assertThat(localContext.getBean(beanName, String.class)).isEqualTo(beanName); + } + } + } + + + @Configuration(proxyBeanMethods = false) + static class TopLevelConfig { + + @Bean + String foo() { + return "foo"; + } + } + + @Configuration(proxyBeanMethods = false) + static class NestedConfig { + + @Bean + String bar() { + return "bar"; + } + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ParameterizedConstructorInjectionTestMethodScopedExtensionContextNestedTests.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ParameterizedConstructorInjectionTestMethodScopedExtensionContextNestedTests.java new file mode 100644 index 00000000000..69d9be4d8a6 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ParameterizedConstructorInjectionTestMethodScopedExtensionContextNestedTests.java @@ -0,0 +1,184 @@ +/* + * Copyright 2002-present 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 + * + * https://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.test.context.junit.jupiter.nested; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInfo; +import org.junit.jupiter.params.ParameterizedClass; +import org.junit.jupiter.params.provider.ValueSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.NestedTestConfiguration; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import org.springframework.test.context.junit.jupiter.nested.ParameterizedConstructorInjectionTestMethodScopedExtensionContextNestedTests.TopLevelConfig; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.OVERRIDE; + +/** + * Parameterized variant of {@link ConstructorInjectionTestMethodScopedExtensionContextNestedTests} + * which tests {@link ParameterizedClass @ParameterizedClass} support. + * + * @author Sam Brannen + * @since 7.0 + */ +@SpringJUnitConfig(TopLevelConfig.class) +@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default +@ParameterizedClass +@ValueSource(strings = {"foo", "bar"}) +class ParameterizedConstructorInjectionTestMethodScopedExtensionContextNestedTests { + + final String beanName; + final String foo; + final ApplicationContext context; + + + ParameterizedConstructorInjectionTestMethodScopedExtensionContextNestedTests( + String beanName, TestInfo testInfo, @Autowired String foo, ApplicationContext context) { + + this.context = context; + this.beanName = beanName; + this.foo = foo; + } + + + @Test + void topLevelTest() { + assertThat(foo).isEqualTo("foo"); + if (beanName.equals("foo")) { + assertThat(context.getBean(beanName, String.class)).isEqualTo(beanName); + } + } + + @Nested + @SpringJUnitConfig(NestedConfig.class) + class AutowiredConstructorTests { + + final String bar; + final ApplicationContext localContext; + + @Autowired + AutowiredConstructorTests(String bar, ApplicationContext context) { + this.bar = bar; + this.localContext = context; + } + + @Test + void nestedTest() { + assertThat(foo).isEqualTo("bar"); + assertThat(bar).isEqualTo("bar"); + if (beanName.equals("bar")) { + assertThat(localContext.getBean(beanName, String.class)).isEqualTo(beanName); + } + } + } + + @Nested + @SpringJUnitConfig(NestedConfig.class) + class AutowiredConstructorParameterTests { + + final String bar; + final ApplicationContext localContext; + + AutowiredConstructorParameterTests(@Autowired String bar, ApplicationContext context) { + this.bar = bar; + this.localContext = context; + } + + @Test + void nestedTest() { + assertThat(foo).isEqualTo("bar"); + assertThat(bar).isEqualTo("bar"); + if (beanName.equals("bar")) { + assertThat(localContext.getBean(beanName, String.class)).isEqualTo(beanName); + } + } + } + + @Nested + @SpringJUnitConfig(NestedConfig.class) + class QualifiedConstructorParameterTests { + + final String bar; + final ApplicationContext localContext; + + QualifiedConstructorParameterTests(TestInfo testInfo, @Qualifier("bar") String s, ApplicationContext context) { + this.bar = s; + this.localContext = context; + } + + @Test + void nestedTest() { + assertThat(foo).isEqualTo("bar"); + assertThat(bar).isEqualTo("bar"); + if (beanName.equals("bar")) { + assertThat(localContext.getBean(beanName, String.class)).isEqualTo(beanName); + } + } + } + + @Nested + @SpringJUnitConfig(NestedConfig.class) + class SpelConstructorParameterTests { + + final String bar; + final int answer; + final ApplicationContext localContext; + + SpelConstructorParameterTests(@Autowired String bar, TestInfo testInfo, @Value("#{ 6 * 7 }") int answer, ApplicationContext context) { + this.bar = bar; + this.answer = answer; + this.localContext = context; + } + + @Test + void nestedTest() { + assertThat(foo).isEqualTo("bar"); + assertThat(bar).isEqualTo("bar"); + assertThat(answer).isEqualTo(42); + if (beanName.equals("bar")) { + assertThat(localContext.getBean(beanName, String.class)).isEqualTo(beanName); + } + } + } + + + @Configuration(proxyBeanMethods = false) + static class TopLevelConfig { + + @Bean + String foo() { + return "foo"; + } + } + + @Configuration(proxyBeanMethods = false) + static class NestedConfig { + + @Bean + String bar() { + return "bar"; + } + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ParameterizedCtxConfigTestClassScopedExtensionContextNestedTests.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ParameterizedCtxConfigTestClassScopedExtensionContextNestedTests.java new file mode 100644 index 00000000000..c160c3e05d4 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ParameterizedCtxConfigTestClassScopedExtensionContextNestedTests.java @@ -0,0 +1,257 @@ +/* + * Copyright 2002-present 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 + * + * https://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.test.context.junit.jupiter.nested; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.Parameter; +import org.junit.jupiter.params.ParameterizedClass; +import org.junit.jupiter.params.provider.ValueSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.NestedTestConfiguration; +import org.springframework.test.context.junit.jupiter.SpringExtensionConfig; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import org.springframework.test.context.junit.jupiter.nested.ParameterizedCtxConfigTestClassScopedExtensionContextNestedTests.TopLevelConfig; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.INHERIT; +import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.OVERRIDE; + +/** + * Parameterized variant of {@link ContextConfigurationTestClassScopedExtensionContextNestedTests} + * which tests {@link ParameterizedClass @ParameterizedClass} support. + * + * @author Sam Brannen + * @since 7.0 + */ +@SpringJUnitConfig(TopLevelConfig.class) +@SpringExtensionConfig(useTestClassScopedExtensionContext = true) +@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default +@ParameterizedClass +@ValueSource(strings = {"foo", "bar"}) +class ParameterizedCtxConfigTestClassScopedExtensionContextNestedTests { + + private static final String FOO = "foo"; + private static final String BAR = "bar"; + private static final String BAZ = "baz"; + + @Parameter + String beanName; + + @Autowired + ApplicationContext context; + + @Autowired + String foo; + + + @Test + void topLevelTest() { + assertThat(foo).isEqualTo(FOO); + if (beanName.equals(FOO)) { + assertThat(context.getBean(beanName, String.class)).isEqualTo(beanName); + } + } + + + @Nested + @SpringJUnitConfig(NestedConfig.class) + class NestedTests { + + @Autowired + ApplicationContext localContext; + + @Autowired(required = false) + @Qualifier("foo") + String localFoo; + + @Autowired + String bar; + + + @Test + void test() { + // In contrast to nested test classes running in JUnit 4, the foo + // field in the outer instance should have been injected from the + // test ApplicationContext for the outer instance. + assertThat(foo).isEqualTo(FOO); + assertThat(this.localFoo).as("foo bean should not be present").isNull(); + assertThat(this.bar).isEqualTo(BAR); + if (beanName.equals(BAR)) { + assertThat(localContext.getBean(beanName, String.class)).isEqualTo(beanName); + } + } + } + + @Nested + @NestedTestConfiguration(INHERIT) + class NestedWithInheritedConfigTests { + + @Autowired + ApplicationContext localContext; + + @Autowired(required = false) + @Qualifier("foo") + String localFoo; + + @Autowired + String bar; + + + @Test + void test() { + // Since the configuration is inherited, the foo field in the outer instance + // and the bar field in the inner instance should both have been injected + // from the test ApplicationContext for the outer instance. + assertThat(foo).isEqualTo(FOO); + assertThat(this.localFoo).isEqualTo(FOO); + assertThat(this.bar).isEqualTo(FOO); + if (beanName.equals(FOO)) { + assertThat(localContext.getBean(beanName, String.class)).isEqualTo(beanName); + } + } + + + @Nested + @NestedTestConfiguration(OVERRIDE) + @SpringJUnitConfig(NestedConfig.class) + class DoubleNestedWithOverriddenConfigTests { + + @Autowired + ApplicationContext localContext; + + @Autowired(required = false) + @Qualifier("foo") + String localFoo; + + @Autowired + String bar; + + + @Test + void test() { + // In contrast to nested test classes running in JUnit 4, the foo + // field in the outer instance should have been injected from the + // test ApplicationContext for the outer instance. + assertThat(foo).isEqualTo(FOO); + assertThat(this.localFoo).as("foo bean should not be present").isNull(); + assertThat(this.bar).isEqualTo(BAR); + if (beanName.equals(BAR)) { + assertThat(localContext.getBean(beanName, String.class)).isEqualTo(beanName); + } + } + + + @Nested + @NestedTestConfiguration(INHERIT) + @ParameterizedClass + @ValueSource(ints = {1, 2}) + class TripleNestedWithInheritedConfigTests { + + @Autowired + ApplicationContext localContext; + + @Autowired(required = false) + @Qualifier("foo") + String localFoo; + + @Autowired + String bar; + + + @Test + void test() { + assertThat(foo).isEqualTo(FOO); + assertThat(this.localFoo).as("foo bean should not be present").isNull(); + assertThat(this.bar).isEqualTo(BAR); + if (beanName.equals(BAR)) { + assertThat(localContext.getBean(beanName, String.class)).isEqualTo(beanName); + } + } + } + + @Nested + @NestedTestConfiguration(INHERIT) + class TripleNestedWithInheritedConfigAndTestInterfaceTests implements TestInterface { + + @Autowired + ApplicationContext localContext; + + @Autowired(required = false) + @Qualifier("foo") + String localFoo; + + @Autowired + String bar; + + @Autowired + String baz; + + + @Test + void test() { + assertThat(foo).isEqualTo(FOO); + assertThat(this.localFoo).as("foo bean should not be present").isNull(); + assertThat(this.bar).isEqualTo(BAR); + assertThat(this.baz).isEqualTo(BAZ); + if (beanName.equals(BAR)) { + assertThat(localContext.getBean(beanName, String.class)).isEqualTo(beanName); + } + } + } + } + } + + + @Configuration(proxyBeanMethods = false) + static class TopLevelConfig { + + @Bean + String foo() { + return FOO; + } + } + + @Configuration(proxyBeanMethods = false) + static class NestedConfig { + + @Bean + String bar() { + return BAR; + } + } + + @Configuration(proxyBeanMethods = false) + static class TestInterfaceConfig { + + @Bean + String baz() { + return BAZ; + } + } + + @ContextConfiguration(classes = TestInterfaceConfig.class) + interface TestInterface { + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ParameterizedCtxConfigTestMethodScopedExtensionContextNestedTests.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ParameterizedCtxConfigTestMethodScopedExtensionContextNestedTests.java new file mode 100644 index 00000000000..a3a3c294898 --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ParameterizedCtxConfigTestMethodScopedExtensionContextNestedTests.java @@ -0,0 +1,249 @@ +/* + * Copyright 2002-present 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 + * + * https://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.test.context.junit.jupiter.nested; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.Parameter; +import org.junit.jupiter.params.ParameterizedClass; +import org.junit.jupiter.params.provider.ValueSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.ApplicationContext; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.NestedTestConfiguration; +import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; +import org.springframework.test.context.junit.jupiter.nested.ParameterizedCtxConfigTestMethodScopedExtensionContextNestedTests.TopLevelConfig; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.INHERIT; +import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.OVERRIDE; + +/** + * Parameterized variant of {@link ContextConfigurationTestMethodScopedExtensionContextNestedTests} + * which tests {@link ParameterizedClass @ParameterizedClass} support. + * + * @author Sam Brannen + * @since 7.0 + */ +@SpringJUnitConfig(TopLevelConfig.class) +@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default +@ParameterizedClass +@ValueSource(strings = {"foo", "bar"}) +class ParameterizedCtxConfigTestMethodScopedExtensionContextNestedTests { + + private static final String FOO = "foo"; + private static final String BAR = "bar"; + private static final String BAZ = "baz"; + + @Parameter + String beanName; + + @Autowired + ApplicationContext context; + + @Autowired(required = false) + @Qualifier("foo") + String foo; + + + @Test + void topLevelTest() { + assertThat(foo).isEqualTo(FOO); + if (beanName.equals(FOO)) { + assertThat(context.getBean(beanName, String.class)).isEqualTo(beanName); + } + } + + + @Nested + @SpringJUnitConfig(NestedConfig.class) + class NestedTests { + + @Autowired + ApplicationContext localContext; + + @Autowired(required = false) + @Qualifier("foo") + String localFoo; + + @Autowired + String bar; + + + @Test + void test() { + assertThat(foo).as("foo bean should not be present").isNull(); + assertThat(this.localFoo).as("local foo bean should not be present").isNull(); + assertThat(this.bar).isEqualTo(BAR); + if (beanName.equals(BAR)) { + assertThat(localContext.getBean(beanName, String.class)).isEqualTo(beanName); + } + } + } + + @Nested + @NestedTestConfiguration(INHERIT) + class NestedTestsWithInheritedConfigTests { + + @Autowired + ApplicationContext localContext; + + @Autowired(required = false) + @Qualifier("foo") + String localFoo; + + @Autowired + String bar; + + + @Test + void test() { + // Since the configuration is inherited, the foo field in the outer instance + // and the bar field in the inner instance should both have been injected + // from the test ApplicationContext for the outer instance. + assertThat(foo).isEqualTo(FOO); + assertThat(this.localFoo).isEqualTo(FOO); + assertThat(this.bar).isEqualTo(FOO); + if (beanName.equals(FOO)) { + assertThat(localContext.getBean(beanName, String.class)).isEqualTo(beanName); + } + } + + + @Nested + @NestedTestConfiguration(OVERRIDE) + @SpringJUnitConfig(NestedConfig.class) + class DoubleNestedWithOverriddenConfigTests { + + @Autowired + ApplicationContext localContext; + + @Autowired(required = false) + @Qualifier("foo") + String localFoo; + + @Autowired + String bar; + + + @Test + void test() { + assertThat(foo).as("foo bean should not be present").isNull(); + assertThat(this.localFoo).as("local foo bean should not be present").isNull(); + assertThat(this.bar).isEqualTo(BAR); + if (beanName.equals(BAR)) { + assertThat(localContext.getBean(beanName, String.class)).isEqualTo(beanName); + } + } + + + @Nested + @NestedTestConfiguration(INHERIT) + class TripleNestedWithInheritedConfigTests { + + @Autowired + ApplicationContext localContext; + + @Autowired(required = false) + @Qualifier("foo") + String localFoo; + + @Autowired + String bar; + + + @Test + void test() { + assertThat(foo).as("foo bean should not be present").isNull(); + assertThat(this.localFoo).as("local foo bean should not be present").isNull(); + assertThat(this.bar).isEqualTo(BAR); + if (beanName.equals(BAR)) { + assertThat(localContext.getBean(beanName, String.class)).isEqualTo(beanName); + } + } + } + + @Nested + @NestedTestConfiguration(INHERIT) + class TripleNestedWithInheritedConfigAndTestInterfaceTests implements TestInterface { + + @Autowired + ApplicationContext localContext; + + @Autowired(required = false) + @Qualifier("foo") + String localFoo; + + @Autowired + @Qualifier("bar") + String bar; + + @Autowired + String baz; + + + @Test + void test() { + assertThat(foo).as("foo bean should not be present").isNull(); + assertThat(this.localFoo).as("local foo bean should not be present").isNull(); + assertThat(this.bar).isEqualTo(BAR); + assertThat(this.baz).isEqualTo(BAZ); + if (beanName.equals(BAR) || beanName.equals(BAZ)) { + assertThat(localContext.getBean(beanName, String.class)).isEqualTo(beanName); + } + } + } + } + } + + + @Configuration(proxyBeanMethods = false) + static class TopLevelConfig { + + @Bean + String foo() { + return FOO; + } + } + + @Configuration(proxyBeanMethods = false) + static class NestedConfig { + + @Bean + String bar() { + return BAR; + } + } + + @Configuration(proxyBeanMethods = false) + static class TestInterfaceConfig { + + @Bean + String baz() { + return BAZ; + } + } + + @ContextConfiguration(classes = TestInterfaceConfig.class) + interface TestInterface { + } + +} diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestConstructorTestClassScopedExtensionContextNestedTests.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestConstructorTestClassScopedExtensionContextNestedTests.java index 6d2da9c7a4f..6f8a7f018c3 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestConstructorTestClassScopedExtensionContextNestedTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestConstructorTestClassScopedExtensionContextNestedTests.java @@ -26,6 +26,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.test.context.NestedTestConfiguration; import org.springframework.test.context.TestConstructor; import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.context.junit.jupiter.SpringExtensionConfig; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import static org.assertj.core.api.Assertions.assertThat; @@ -44,6 +45,7 @@ import static org.springframework.test.context.TestConstructor.AutowireMode.ANNO * @since 5.3 */ @SpringJUnitConfig +@SpringExtensionConfig(useTestClassScopedExtensionContext = true) @TestConstructor(autowireMode = ALL) @NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default class TestConstructorTestClassScopedExtensionContextNestedTests { diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestConstructorTestMethodScopedExtensionContextNestedTests.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestConstructorTestMethodScopedExtensionContextNestedTests.java index 21d423155f2..cffd997dba8 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestConstructorTestMethodScopedExtensionContextNestedTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestConstructorTestMethodScopedExtensionContextNestedTests.java @@ -19,7 +19,6 @@ package org.springframework.test.context.junit.jupiter.nested; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope; -import org.junit.platform.testkit.engine.EngineTestKit; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; @@ -30,9 +29,6 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope.DEFAULT_SCOPE_PROPERTY_NAME; -import static org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope.TEST_METHOD; -import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.INHERIT; import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.OVERRIDE; import static org.springframework.test.context.TestConstructor.AutowireMode.ALL; @@ -47,53 +43,52 @@ import static org.springframework.test.context.TestConstructor.AutowireMode.ANNO * @author Sam Brannen * @since 6.2.13 */ +@SpringJUnitConfig +@TestConstructor(autowireMode = ALL) +@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default class TestConstructorTestMethodScopedExtensionContextNestedTests { + TestConstructorTestMethodScopedExtensionContextNestedTests(String text) { + assertThat(text).isEqualTo("enigma"); + } + @Test - void runTests() { - EngineTestKit.engine("junit-jupiter") - .configurationParameter(DEFAULT_SCOPE_PROPERTY_NAME, TEST_METHOD.name()) - .selectors(selectClass(TestCase.class)) - .execute() - .testEvents() - .assertStatistics(stats -> stats.started(8).succeeded(8).failed(0)); + void test() { } + @Nested @SpringJUnitConfig(Config.class) - @TestConstructor(autowireMode = ALL) - @NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default - static class TestCase { + @TestConstructor(autowireMode = ANNOTATED) + class ConfigOverriddenByDefaultTests { - TestCase(String text) { + @Autowired + ConfigOverriddenByDefaultTests(String text) { assertThat(text).isEqualTo("enigma"); } @Test void test() { } + } + @Nested + @NestedTestConfiguration(INHERIT) + class InheritedConfigTests { - @Nested - @SpringJUnitConfig(Config.class) - @TestConstructor(autowireMode = ANNOTATED) - class ConfigOverriddenByDefaultTestCase { - - @Autowired - ConfigOverriddenByDefaultTestCase(String text) { - assertThat(text).isEqualTo("enigma"); - } + InheritedConfigTests(String text) { + assertThat(text).isEqualTo("enigma"); + } - @Test - void test() { - } + @Test + void test() { } + @Nested - @NestedTestConfiguration(INHERIT) - class InheritedConfigTestCase { + class DoubleNestedWithImplicitlyInheritedConfigTests { - InheritedConfigTestCase(String text) { + DoubleNestedWithImplicitlyInheritedConfigTests(String text) { assertThat(text).isEqualTo("enigma"); } @@ -103,70 +98,57 @@ class TestConstructorTestMethodScopedExtensionContextNestedTests { @Nested - class DoubleNestedWithImplicitlyInheritedConfigTestCase { + class TripleNestedWithImplicitlyInheritedConfigTests { - DoubleNestedWithImplicitlyInheritedConfigTestCase(String text) { + TripleNestedWithImplicitlyInheritedConfigTests(String text) { assertThat(text).isEqualTo("enigma"); } @Test void test() { } + } + } + @Nested + @NestedTestConfiguration(OVERRIDE) + @SpringJUnitConfig(Config.class) + @TestConstructor(autowireMode = ANNOTATED) + class DoubleNestedWithOverriddenConfigTests { - @Nested - class TripleNestedWithImplicitlyInheritedConfigTestCase { - - TripleNestedWithImplicitlyInheritedConfigTestCase(String text) { - assertThat(text).isEqualTo("enigma"); - } + DoubleNestedWithOverriddenConfigTests(@Autowired String text) { + assertThat(text).isEqualTo("enigma"); + } - @Test - void test() { - } - } + @Test + void test() { } + @Nested - @NestedTestConfiguration(OVERRIDE) - @SpringJUnitConfig(Config.class) - @TestConstructor(autowireMode = ANNOTATED) - class DoubleNestedWithOverriddenConfigTestCase { + @NestedTestConfiguration(INHERIT) + class TripleNestedWithInheritedConfigTests { - DoubleNestedWithOverriddenConfigTestCase(@Autowired String text) { + @Autowired + TripleNestedWithInheritedConfigTests(String text) { assertThat(text).isEqualTo("enigma"); } @Test void test() { } + } + @Nested + @NestedTestConfiguration(INHERIT) + class TripleNestedWithInheritedConfigAndTestInterfaceTests implements TestInterface { - @Nested - @NestedTestConfiguration(INHERIT) - class TripleNestedWithInheritedConfigTestCase { - - @Autowired - TripleNestedWithInheritedConfigTestCase(String text) { - assertThat(text).isEqualTo("enigma"); - } - - @Test - void test() { - } + TripleNestedWithInheritedConfigAndTestInterfaceTests(String text) { + assertThat(text).isEqualTo("enigma"); } - @Nested - @NestedTestConfiguration(INHERIT) - class TripleNestedWithInheritedConfigAndTestInterfaceTestCase implements TestInterface { - - TripleNestedWithInheritedConfigAndTestInterfaceTestCase(String text) { - assertThat(text).isEqualTo("enigma"); - } - - @Test - void test() { - } + @Test + void test() { } } } diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestPropertySourceTestClassScopedExtensionContextNestedTests.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestPropertySourceTestClassScopedExtensionContextNestedTests.java index 6f1744da48f..5927cfa227b 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestPropertySourceTestClassScopedExtensionContextNestedTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestPropertySourceTestClassScopedExtensionContextNestedTests.java @@ -26,6 +26,7 @@ import org.springframework.core.env.Environment; import org.springframework.test.context.NestedTestConfiguration; import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.context.junit.jupiter.SpringExtensionConfig; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import static org.assertj.core.api.Assertions.assertThat; @@ -42,6 +43,7 @@ import static org.springframework.test.context.NestedTestConfiguration.Enclosing * @since 5.3 */ @SpringJUnitConfig +@SpringExtensionConfig(useTestClassScopedExtensionContext = true) @TestPropertySource(properties = "p1 = v1") @NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default class TestPropertySourceTestClassScopedExtensionContextNestedTests { diff --git a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestPropertySourceTestMethodScopedExtensionContextNestedTests.java b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestPropertySourceTestMethodScopedExtensionContextNestedTests.java index 9be4d3db645..6a1e8ac1673 100644 --- a/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestPropertySourceTestMethodScopedExtensionContextNestedTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestPropertySourceTestMethodScopedExtensionContextNestedTests.java @@ -19,7 +19,6 @@ package org.springframework.test.context.junit.jupiter.nested; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope; -import org.junit.platform.testkit.engine.EngineTestKit; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; @@ -30,9 +29,6 @@ import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope.DEFAULT_SCOPE_PROPERTY_NAME; -import static org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope.TEST_METHOD; -import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.INHERIT; import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.OVERRIDE; @@ -45,139 +41,125 @@ import static org.springframework.test.context.NestedTestConfiguration.Enclosing * @author Sam Brannen * @since 6.2.13 */ +@SpringJUnitConfig +@TestPropertySource(properties = "p1 = v1") +@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default class TestPropertySourceTestMethodScopedExtensionContextNestedTests { + @Autowired + Environment env1; + + @Test - void runTests() { - EngineTestKit.engine("junit-jupiter") - .configurationParameter(DEFAULT_SCOPE_PROPERTY_NAME, TEST_METHOD.name()) - .selectors(selectClass(TestCase.class)) - .execute() - .testEvents() - .assertStatistics(stats -> stats.started(7).succeeded(7).failed(0)); + void propertiesInEnvironment() { + assertThat(env1.getProperty("p1")).isEqualTo("v1"); } - @SpringJUnitConfig(Config.class) - @TestPropertySource(properties = "p1 = v1") - @NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default - static class TestCase { + @Nested + @NestedTestConfiguration(INHERIT) + class InheritedCfgTests { @Autowired - Environment env1; + Environment env2; @Test void propertiesInEnvironment() { - assertThat(env1.getProperty("p1")).isEqualTo("v1"); + assertThat(env1).isSameAs(env2); + assertThat(env2.getProperty("p1")).isEqualTo("v1"); } + } + @Nested + @SpringJUnitConfig(Config.class) + @TestPropertySource(properties = "p2 = v2") + class ConfigOverriddenByDefaultTests { - @Nested - @NestedTestConfiguration(INHERIT) - class InheritedCfgTestCase { - - @Autowired - Environment env2; + @Autowired + Environment env2; - @Test - void propertiesInEnvironment() { - assertThat(env1).isSameAs(env2); - assertThat(env2.getProperty("p1")).isEqualTo("v1"); - } + @Test + void propertiesInEnvironment() { + assertThat(env1).isSameAs(env2); + assertThat(env2.getProperty("p1")).isNull(); + assertThat(env2.getProperty("p2")).isEqualTo("v2"); } + } - @Nested - @SpringJUnitConfig(Config.class) - @TestPropertySource(properties = "p2 = v2") - class ConfigOverriddenByDefaultTestCase { + @Nested + @NestedTestConfiguration(INHERIT) + @TestPropertySource(properties = "p2a = v2a") + @TestPropertySource(properties = "p2b = v2b") + class InheritedAndExtendedCfgTests { - @Autowired - Environment env2; + @Autowired + Environment env2; - @Test - void propertiesInEnvironment() { - assertThat(env1).isSameAs(env2); - assertThat(env2.getProperty("p1")).isNull(); - assertThat(env2.getProperty("p2")).isEqualTo("v2"); - } + @Test + void propertiesInEnvironment() { + assertThat(env1).isSameAs(env2); + assertThat(env2.getProperty("p1")).isEqualTo("v1"); + assertThat(env2.getProperty("p2a")).isEqualTo("v2a"); + assertThat(env2.getProperty("p2b")).isEqualTo("v2b"); } + @Nested - @NestedTestConfiguration(INHERIT) - @TestPropertySource(properties = "p2a = v2a") - @TestPropertySource(properties = "p2b = v2b") - class InheritedAndExtendedCfgTestCase { + @NestedTestConfiguration(OVERRIDE) + @SpringJUnitConfig(Config.class) + @TestPropertySource(properties = "p3 = v3") + class L3OverriddenCfgTests { @Autowired - Environment env2; + Environment env3; @Test void propertiesInEnvironment() { - assertThat(env1).isSameAs(env2); - assertThat(env2.getProperty("p1")).isEqualTo("v1"); - assertThat(env2.getProperty("p2a")).isEqualTo("v2a"); - assertThat(env2.getProperty("p2b")).isEqualTo("v2b"); + assertThat(env1).isSameAs(env2).isSameAs(env3); + assertThat(env3.getProperty("p1")).isNull(); + assertThat(env3.getProperty("p2")).isNull(); + assertThat(env3.getProperty("p3")).isEqualTo("v3"); } @Nested - @NestedTestConfiguration(OVERRIDE) - @SpringJUnitConfig(Config.class) - @TestPropertySource(properties = "p3 = v3") - class L3OverriddenCfgTestCase { + @NestedTestConfiguration(INHERIT) + @TestPropertySource(properties = {"p3 = v34", "p4 = v4"}, inheritProperties = false) + class L4InheritedCfgButOverriddenTestPropsTests { @Autowired - Environment env3; + Environment env4; @Test void propertiesInEnvironment() { - assertThat(env1).isSameAs(env2).isSameAs(env3); - assertThat(env3.getProperty("p1")).isNull(); - assertThat(env3.getProperty("p2")).isNull(); - assertThat(env3.getProperty("p3")).isEqualTo("v3"); + assertThat(env1).isSameAs(env2).isSameAs(env3).isSameAs(env4); + assertThat(env4.getProperty("p1")).isNull(); + assertThat(env4.getProperty("p2")).isNull(); + assertThat(env4.getProperty("p3")).isEqualTo("v34"); + assertThat(env4.getProperty("p4")).isEqualTo("v4"); } - @Nested - @NestedTestConfiguration(INHERIT) - @TestPropertySource(properties = {"p3 = v34", "p4 = v4"}, inheritProperties = false) - class L4InheritedCfgButOverriddenTestPropertiesTestCase { + class L5InheritedCfgAndTestInterfaceTests implements TestInterface { @Autowired - Environment env4; + Environment env5; @Test void propertiesInEnvironment() { - assertThat(env1).isSameAs(env2).isSameAs(env3).isSameAs(env4); - assertThat(env4.getProperty("p1")).isNull(); - assertThat(env4.getProperty("p2")).isNull(); - assertThat(env4.getProperty("p3")).isEqualTo("v34"); - assertThat(env4.getProperty("p4")).isEqualTo("v4"); - } - - @Nested - class L5InheritedCfgAndTestInterfaceTestCase implements TestInterface { - - @Autowired - Environment env5; - - - @Test - void propertiesInEnvironment() { - assertThat(env4).isSameAs(env5); - assertThat(env5.getProperty("p1")).isNull(); - assertThat(env5.getProperty("p2")).isNull(); - assertThat(env5.getProperty("p3")).isEqualTo("v34"); - assertThat(env5.getProperty("p4")).isEqualTo("v4"); - assertThat(env5.getProperty("foo")).isEqualTo("bar"); - assertThat(env5.getProperty("enigma")).isEqualTo("42"); - } + assertThat(env4).isSameAs(env5); + assertThat(env5.getProperty("p1")).isNull(); + assertThat(env5.getProperty("p2")).isNull(); + assertThat(env5.getProperty("p3")).isEqualTo("v34"); + assertThat(env5.getProperty("p4")).isEqualTo("v4"); + assertThat(env5.getProperty("foo")).isEqualTo("bar"); + assertThat(env5.getProperty("enigma")).isEqualTo("42"); } } } diff --git a/spring-test/src/test/java/org/springframework/test/context/orm/jpa/JpaPersonRepositoryTests.java b/spring-test/src/test/java/org/springframework/test/context/orm/jpa/JpaPersonRepositoryTests.java index 9811a848d55..14eb4aa90ac 100644 --- a/spring-test/src/test/java/org/springframework/test/context/orm/jpa/JpaPersonRepositoryTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/orm/jpa/JpaPersonRepositoryTests.java @@ -21,10 +21,6 @@ import jakarta.persistence.PersistenceContext; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope; -import org.junit.platform.suite.api.ConfigurationParameter; -import org.junit.platform.suite.api.SelectClasses; -import org.junit.platform.suite.api.Suite; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.TestPropertySource; @@ -37,62 +33,45 @@ import org.springframework.transaction.annotation.Transactional; import static org.assertj.core.api.Assertions.assertThat; /** - * Test {@link Suite @Suite} which selects a single test class and runs it with - * {@link ExtensionContextScope#TEST_METHOD}. + * Transactional tests for JPA support with {@link Nested @Nested} test classes. * * @author Sam Brannen * @since 6.2.13 * @see issue gh-34576 */ -@Suite -@SelectClasses(JpaPersonRepositoryTests.TestCase.class) -@ConfigurationParameter( - key = ExtensionContextScope.DEFAULT_SCOPE_PROPERTY_NAME, - value = "test_method" // If this is changed to "default", NestedTests will fail. -) -// Even though this is a @Suite, it is intentionally named JpaPersonRepositoryTests -// instead of JpaPersonRepositoryTestSuite, so that it is run with the Gradle build -// due to the "*Tests" naming convention. +@SpringJUnitConfig(JpaConfig.class) +@Transactional +@Sql(statements = "insert into person(id, name) values(0, 'Jane')") class JpaPersonRepositoryTests { - /** - * Transactional tests for JPA support with {@link Nested @Nested} test classes. - */ - @SpringJUnitConfig(JpaConfig.class) - @Transactional - @Sql(statements = "insert into person(id, name) values(0, 'Jane')") - static class TestCase { + @PersistenceContext + EntityManager em; - @PersistenceContext - EntityManager em; + @Autowired + PersonRepository repo; - @Autowired - PersonRepository repo; + @BeforeEach + void setup() { + em.persist(new Person("John")); + em.flush(); + } - @BeforeEach - void setup() { - em.persist(new Person("John")); - em.flush(); - } + @Test + void findAll() { + assertThat(repo.findAll()).map(Person::getName).containsExactlyInAnyOrder("Jane", "John"); + } + + + @Nested + // Declare a random test property to ensure we get a different ApplicationContext. + @TestPropertySource(properties = "nested = true") + class NestedTests { @Test void findAll() { assertThat(repo.findAll()).map(Person::getName).containsExactlyInAnyOrder("Jane", "John"); } - - - @Nested - // Declare a random test property to ensure we get a different ApplicationContext. - @TestPropertySource(properties = "nested = true") - class NestedTests { - - @Test - void findAll() { - assertThat(repo.findAll()).map(Person::getName).containsExactlyInAnyOrder("Jane", "John"); - } - } - } }