Use test-method scoped ExtensionContext in the SpringExtension

As of Spring Framework 6.2.13, we support JUnit Jupiter 5.12's
ExtensionContextScope.TEST_METHOD behavior in the SpringExtension and
the BeanOverrideTestExecutionListener; however, users can only benefit
from that if they explicitly set the following configuration parameter
for their entire test suite, which may have adverse effects on other
third-party JUnit Jupiter extensions.

junit.jupiter.extensions.testinstantiation.extensioncontextscope.default=test_method

For Spring Framework 7.0, in order to support dependency injection into
test class constructors and fields in @⁠Nested test class hierarchies
from the same ApplicationContext that is already used to perform
dependency injection into lifecycle and test methods (@⁠BeforeEach,
@⁠AfterEach, @⁠Test, etc.), we have decided to configure the
SpringExtension to use ExtensionContextScope.TEST_METHOD by default. In
addition, we have decided to provide a mechanism for users to switch
back to the legacy "test-class scoped ExtensionContext" behavior in
case third-party TestExecutionListener implementations are not yet
compatible with test-method scoped ExtensionContext and TestContext
semantics.

This commit achieves the above goals as follows.

- A new @⁠SpringExtensionConfig annotation has been introduced, which
  allows developers to configure the effective ExtensionContext scope
  used by the SpringExtension.

- The SpringExtension now overrides
  getTestInstantiationExtensionContextScope() to return
  ExtensionContextScope.TEST_METHOD.

- The postProcessTestInstance() and resolveParameter() methods in the
  SpringExtension now find the properly scoped ExtensionContext for the
  supplied test class, based on whether the @⁠Nested test class
  hierarchy is annotated with
  @⁠SpringExtensionConfig(useTestClassScopedExtensionContext = true).

See gh-35680
See gh-35716
Closes gh-35697
This commit is contained in:
Sam Brannen
2025-10-30 13:54:16 +01:00
parent b5557160e0
commit 41ae13df5d
32 changed files with 1667 additions and 783 deletions
@@ -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")
@@ -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 {
@Nested
@DisplayName("With @TestBean in enclosing class and in @Nested class")
public class TestBeanFieldInEnclosingClassTests {
@TestBean(name = "field")
String field;
@TestBean(name = "nestedField")
String nestedField;
@TestBean(name = "methodRenamed1", methodName = "field")
String methodRenamed1;
@TestBean(name = "methodRenamed2", methodName = "nestedField")
String methodRenamed2;
static String field() {
return "fieldOverride";
}
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");
}
@Test
void nestedFieldWithMethodNameHasOverride(ApplicationContext ctx) {
assertThat(ctx.getBean("methodRenamed2")).as("applicationContext").isEqualTo("nestedFieldOverride");
assertThat(methodRenamed2).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;
@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 {
@Nested
@DisplayName("With factory method in enclosing class")
public class TestBeanFactoryMethodInEnclosingClassTests {
@Test
void fieldHasOverride(ApplicationContext ctx) {
assertThat(ctx.getBean("field")).as("applicationContext").isEqualTo("fieldOverride");
assertThat(field).as("injection point").isEqualTo("fieldOverride");
}
@TestBean(methodName = "nestedField", name = "nestedField")
String nestedField;
@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");
}
}
@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");
}
}
}
@@ -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")
@@ -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();
}
@SpringJUnitConfig
public static class TestCase {
@Nested
@DisplayName("With @MockitoBean in enclosing class and in @Nested class")
public class MockitoBeanNestedTests {
@MockitoBean("field")
ExampleService field;
@Autowired
@Qualifier("field")
ExampleService localField;
@MockitoBean("nonExistingBean")
ExampleService nonExisting;
@Autowired
@Qualifier("nonExistingBean")
ExampleService localNonExisting;
@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);
}
}
@@ -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")
@@ -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 {
@@ -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 {
@@ -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,37 +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<String> 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<String> strings;
List<String> 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 {
@Autowired
List<String> localStrings;
@Test
void test() {
assertThat(strings)
.isEqualTo(this.localStrings)
.containsExactlyInAnyOrder("Y", "A2");
}
}
@Nested
@NestedTestConfiguration(INHERIT)
@ContextConfiguration(classes = Config2.class)
@ActiveProfiles("2")
class InheritedAndExtendedConfigTests {
@Autowired
List<String> localStrings;
@Test
void test() {
assertThat(strings)
.isEqualTo(this.localStrings)
.containsExactlyInAnyOrder("X", "A1", "Y", "A2");
}
@Nested
@NestedTestConfiguration(INHERIT)
class InheritedConfigTestCase {
@NestedTestConfiguration(OVERRIDE)
@SpringJUnitConfig({ Config1.class, Config2.class, Config3.class })
@ActiveProfiles("3")
class DoubleNestedWithOverriddenConfigTests {
@Autowired
List<String> localStrings;
@@ -89,50 +126,14 @@ class ActiveProfilesTestMethodScopedExtensionContextNestedTests {
void test() {
assertThat(strings)
.isEqualTo(this.localStrings)
.containsExactlyInAnyOrder("X", "A1");
}
}
@Nested
@SpringJUnitConfig(Config2.class)
@ActiveProfiles("2")
class ConfigOverriddenByDefaultTestCase {
@Autowired
List<String> localStrings;
@Test
void test() {
assertThat(strings)
.isEqualTo(this.localStrings)
.containsExactlyInAnyOrder("Y", "A2");
}
}
@Nested
@NestedTestConfiguration(INHERIT)
@ContextConfiguration(classes = Config2.class)
@ActiveProfiles("2")
class InheritedAndExtendedConfigTestCase {
@Autowired
List<String> localStrings;
@Test
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<String> localStrings;
@@ -142,41 +143,23 @@ class ActiveProfilesTestMethodScopedExtensionContextNestedTests {
void test() {
assertThat(strings)
.isEqualTo(this.localStrings)
.containsExactlyInAnyOrder("X", "Y", "Z", "A3");
.containsExactlyInAnyOrder("X", "Y", "Z", "A2");
}
}
@Nested
@NestedTestConfiguration(INHERIT)
class TripleNestedWithInheritedConfigAndTestInterfaceTests implements TestInterface {
@Autowired
List<String> localStrings;
@Nested
@NestedTestConfiguration(INHERIT)
@ActiveProfiles(profiles = "2", inheritProfiles = false)
class TripleNestedWithInheritedConfigButOverriddenProfilesTestCase {
@Autowired
List<String> localStrings;
@Test
void test() {
assertThat(strings)
.isEqualTo(this.localStrings)
.containsExactlyInAnyOrder("X", "Y", "Z", "A2");
}
}
@Nested
@NestedTestConfiguration(INHERIT)
class TripleNestedWithInheritedConfigAndTestInterfaceTestCase implements TestInterface {
@Autowired
List<String> 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");
}
}
}
@@ -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 {
@@ -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 AutowiredConstructorParameterTests {
final String bar;
AutowiredConstructorParameterTests(@Autowired String bar) {
this.bar = bar;
}
@Nested
@SpringJUnitConfig(NestedConfig.class)
class AutowiredConstructorTestCase {
@Test
void nestedTest() {
assertThat(foo).isEqualTo("bar");
assertThat(bar).isEqualTo("bar");
}
}
final String bar;
@Nested
@SpringJUnitConfig(NestedConfig.class)
class QualifiedConstructorParameterTests {
@Autowired
AutowiredConstructorTestCase(String bar) {
this.bar = bar;
}
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 AutowiredConstructorParameterTestCase {
@Test
void nestedTest() {
assertThat(foo).isEqualTo("bar");
assertThat(bar).isEqualTo("bar");
}
}
final String bar;
@Nested
@SpringJUnitConfig(NestedConfig.class)
class SpelConstructorParameterTests {
AutowiredConstructorParameterTestCase(@Autowired String bar) {
this.bar = bar;
}
final String bar;
final int answer;
@Test
void nestedTest() {
assertThat(foo).isEqualTo("bar");
assertThat(bar).isEqualTo("bar");
}
SpelConstructorParameterTests(@Autowired String bar, TestInfo testInfo, @Value("#{ 6 * 7 }") int answer) {
this.bar = bar;
this.answer = answer;
}
@Nested
@SpringJUnitConfig(NestedConfig.class)
class QualifiedConstructorParameterTestCase {
final String bar;
QualifiedConstructorParameterTestCase(TestInfo testInfo, @Qualifier("bar") String s) {
this.bar = s;
}
@Test
void nestedTest() {
assertThat(foo).isEqualTo("bar");
assertThat(bar).isEqualTo("bar");
}
@Test
void nestedTest() {
assertThat(foo).isEqualTo("bar");
assertThat(bar).isEqualTo("bar");
assertThat(answer).isEqualTo(42);
}
@Nested
@SpringJUnitConfig(NestedConfig.class)
class SpelConstructorParameterTestCase {
final String bar;
final int answer;
SpelConstructorParameterTestCase(@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);
}
}
}
// -------------------------------------------------------------------------
@@ -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 {
@@ -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 {
private static final String FOO = "foo";
private static final String BAR = "bar";
private static final String BAZ = "baz";
@Nested
@SpringJUnitConfig(NestedConfig.class)
class NestedTests {
@Autowired(required = false)
@Qualifier("foo")
String foo;
String localFoo;
@Autowired
String bar;
@Test
void topLevelTest() {
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 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 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 {
@Autowired(required = false)
@Qualifier("foo")
String localFoo;
@Autowired
@Qualifier("bar")
String bar;
@Autowired
String baz;
@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
@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);
}
@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);
}
}
}
}
// -------------------------------------------------------------------------
@@ -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")
@@ -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
@NestedTestConfiguration(INHERIT)
@ContextConfiguration(classes = Child1Config.class)
class NestedInheritedCfgTests {
@Autowired
String bar;
@Autowired
ApplicationContext context;
@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
@ContextConfiguration(classes = NestedConfig.class)
class NestedTestCase {
@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);
}
}
@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);
}
}
}
}
}
// -------------------------------------------------------------------------
@@ -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";
}
}
}
@@ -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";
}
}
}
@@ -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 {
}
}
@@ -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 {
}
}
@@ -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 {
@@ -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,25 +43,40 @@ 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 {
InheritedConfigTests(String text) {
assertThat(text).isEqualTo("enigma");
}
@@ -75,25 +86,37 @@ class TestConstructorTestMethodScopedExtensionContextNestedTests {
@Nested
@SpringJUnitConfig(Config.class)
@TestConstructor(autowireMode = ANNOTATED)
class ConfigOverriddenByDefaultTestCase {
class DoubleNestedWithImplicitlyInheritedConfigTests {
@Autowired
ConfigOverriddenByDefaultTestCase(String text) {
DoubleNestedWithImplicitlyInheritedConfigTests(String text) {
assertThat(text).isEqualTo("enigma");
}
@Test
void test() {
}
@Nested
class TripleNestedWithImplicitlyInheritedConfigTests {
TripleNestedWithImplicitlyInheritedConfigTests(String text) {
assertThat(text).isEqualTo("enigma");
}
@Test
void test() {
}
}
}
@Nested
@NestedTestConfiguration(INHERIT)
class InheritedConfigTestCase {
@NestedTestConfiguration(OVERRIDE)
@SpringJUnitConfig(Config.class)
@TestConstructor(autowireMode = ANNOTATED)
class DoubleNestedWithOverriddenConfigTests {
InheritedConfigTestCase(String text) {
DoubleNestedWithOverriddenConfigTests(@Autowired String text) {
assertThat(text).isEqualTo("enigma");
}
@@ -103,71 +126,30 @@ class TestConstructorTestMethodScopedExtensionContextNestedTests {
@Nested
class DoubleNestedWithImplicitlyInheritedConfigTestCase {
@NestedTestConfiguration(INHERIT)
class TripleNestedWithInheritedConfigTests {
DoubleNestedWithImplicitlyInheritedConfigTestCase(String text) {
@Autowired
TripleNestedWithInheritedConfigTests(String text) {
assertThat(text).isEqualTo("enigma");
}
@Test
void test() {
}
@Nested
class TripleNestedWithImplicitlyInheritedConfigTestCase {
TripleNestedWithImplicitlyInheritedConfigTestCase(String text) {
assertThat(text).isEqualTo("enigma");
}
@Test
void test() {
}
}
}
@Nested
@NestedTestConfiguration(OVERRIDE)
@SpringJUnitConfig(Config.class)
@TestConstructor(autowireMode = ANNOTATED)
class DoubleNestedWithOverriddenConfigTestCase {
@NestedTestConfiguration(INHERIT)
class TripleNestedWithInheritedConfigAndTestInterfaceTests implements TestInterface {
DoubleNestedWithOverriddenConfigTestCase(@Autowired String text) {
TripleNestedWithInheritedConfigAndTestInterfaceTests(String text) {
assertThat(text).isEqualTo("enigma");
}
@Test
void test() {
}
@Nested
@NestedTestConfiguration(INHERIT)
class TripleNestedWithInheritedConfigTestCase {
@Autowired
TripleNestedWithInheritedConfigTestCase(String text) {
assertThat(text).isEqualTo("enigma");
}
@Test
void test() {
}
}
@Nested
@NestedTestConfiguration(INHERIT)
class TripleNestedWithInheritedConfigAndTestInterfaceTestCase implements TestInterface {
TripleNestedWithInheritedConfigAndTestInterfaceTestCase(String text) {
assertThat(text).isEqualTo("enigma");
}
@Test
void test() {
}
}
}
}
}
@@ -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 {
@@ -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 {
@Autowired
Environment env2;
@Test
void propertiesInEnvironment() {
assertThat(env1).isSameAs(env2);
assertThat(env2.getProperty("p1")).isNull();
assertThat(env2.getProperty("p2")).isEqualTo("v2");
}
}
@Nested
@NestedTestConfiguration(INHERIT)
@TestPropertySource(properties = "p2a = v2a")
@TestPropertySource(properties = "p2b = v2b")
class InheritedAndExtendedCfgTests {
@Autowired
Environment env2;
@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)
class InheritedCfgTestCase {
@Autowired
Environment env2;
@Test
void propertiesInEnvironment() {
assertThat(env1).isSameAs(env2);
assertThat(env2.getProperty("p1")).isEqualTo("v1");
}
}
@Nested
@NestedTestConfiguration(OVERRIDE)
@SpringJUnitConfig(Config.class)
@TestPropertySource(properties = "p2 = v2")
class ConfigOverriddenByDefaultTestCase {
@TestPropertySource(properties = "p3 = v3")
class L3OverriddenCfgTests {
@Autowired
Environment env2;
Environment env3;
@Test
void propertiesInEnvironment() {
assertThat(env1).isSameAs(env2);
assertThat(env2.getProperty("p1")).isNull();
assertThat(env2.getProperty("p2")).isEqualTo("v2");
}
}
@Nested
@NestedTestConfiguration(INHERIT)
@TestPropertySource(properties = "p2a = v2a")
@TestPropertySource(properties = "p2b = v2b")
class InheritedAndExtendedCfgTestCase {
@Autowired
Environment env2;
@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");
}
}
}
@@ -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 <a href="https://github.com/spring-projects/spring-framework/issues/34576">issue gh-34576</a>
*/
@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");
}
}
}
}