Browse Source

Support JUnit Jupiter ExtensionContextScope.TEST_METHOD

Historically, @⁠Autowired fields in an enclosing class of a @⁠Nested
test class have been injected from the ApplicationContext for the
enclosing class. If the enclosing test class and @⁠Nested test class
share the same ApplicationContext configuration, things work as
developers expect. However, if the enclosing class and @⁠Nested test
class have different ApplicationContexts, that can lead to
difficult-to-debug scenarios. For example, a bean injected into the
enclosing test class will not participate in a test-managed transaction
in the @⁠Nested test class (see gh-34576).

JUnit Jupiter 5.12 introduced a new ExtensionContextScope feature which
allows the SpringExtension to behave the same for @⁠Autowired fields as
it already does for @⁠Autowired arguments in lifecycle and test
methods. Specifically, if a developer sets the ExtensionContextScope to
TEST_METHOD — for example, by configuring the following configuration
parameter as a JVM system property or in a `junit-platform.properties`
file — the SpringExtension already supports dependency injection from
the current, @⁠Nested ApplicationContext in @⁠Autowired fields in an
enclosing class of the @⁠Nested test class.

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

However, there are two scenarios that fail as of Spring Framework
6.2.12.

1. @⁠TestConstructor configuration in @⁠Nested class hierarchies.
2. Field injection for bean overrides (such as @⁠MockitoBean) in
   @⁠Nested class hierarchies.

Commit 82c34f7b51 fixed the SpringExtension to support scenario #2
above.

To fix scenario #1, this commit revises
BeanOverrideTestExecutionListener's injectField() implementation to
look up the fields to inject for the "current test instance" instead of
for the "current test class".

This commit also introduces tests for both scenarios.

See gh-34576
See gh-35676
Closes gh-35680
pull/35687/head
Sam Brannen 2 months ago
parent
commit
d24a31d469
  1. 12
      spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideTestExecutionListener.java
  2. 6
      spring-test/src/test/java/org/springframework/test/context/bean/override/convention/TestBeanByNameLookupTestClassScopedExtensionContextIntegrationTests.java
  3. 205
      spring-test/src/test/java/org/springframework/test/context/bean/override/convention/TestBeanByNameLookupTestMethodScopedExtensionContextIntegrationTests.java
  4. 6
      spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanByNameLookupTestClassScopedExtensionContextIntegrationTests.java
  5. 164
      spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanByNameLookupTestMethodScopedExtensionContextIntegrationTests.java
  6. 8
      spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanByNameLookupTestClassScopedExtensionContextIntegrationTests.java
  7. 126
      spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanByNameLookupTestMethodScopedExtensionContextIntegrationTests.java
  8. 13
      spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ActiveProfilesTestClassScopedExtensionContextNestedTests.java
  9. 236
      spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ActiveProfilesTestMethodScopedExtensionContextNestedTests.java
  10. 14
      spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ConstructorInjectionTestClassScopedExtensionContextNestedTests.java
  11. 173
      spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ConstructorInjectionTestMethodScopedExtensionContextNestedTests.java
  12. 10
      spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextConfigurationTestClassScopedExtensionContextNestedTests.java
  13. 234
      spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextConfigurationTestMethodScopedExtensionContextNestedTests.java
  14. 14
      spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextHierarchyTestClassScopedExtensionContextNestedTests.java
  15. 261
      spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextHierarchyTestMethodScopedExtensionContextNestedTests.java
  16. 8
      spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestConstructorTestClassScopedExtensionContextNestedTests.java
  17. 190
      spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestConstructorTestMethodScopedExtensionContextNestedTests.java
  18. 18
      spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestPropertySourceTestClassScopedExtensionContextNestedTests.java
  19. 198
      spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestPropertySourceTestMethodScopedExtensionContextNestedTests.java
  20. 3
      spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/WebAppConfigurationNestedTests.java
  21. 3
      spring-test/src/test/java/org/springframework/test/context/junit4/nested/NestedTestsWithSpringRulesTests.java

12
spring-test/src/main/java/org/springframework/test/context/bean/override/BeanOverrideTestExecutionListener.java

@ -93,9 +93,17 @@ public class BeanOverrideTestExecutionListener extends AbstractTestExecutionList
* a corresponding bean override instance. * a corresponding bean override instance.
*/ */
private static void injectFields(TestContext testContext) { private static void injectFields(TestContext testContext) {
List<BeanOverrideHandler> handlers = BeanOverrideHandler.forTestClass(testContext.getTestClass()); Object testInstance = testContext.getTestInstance();
// Since JUnit Jupiter 5.12, if the SpringExtension is used with Jupiter's
// ExtensionContextScope.TEST_METHOD mode, the value returned from
// testContext.getTestClass() may refer to the declaring class of the test
// method which is about to be invoked (which may be in a @Nested class
// within the class for the test instance). Thus, we use the class for the
// test instance as the "test class".
Class<?> testClass = testInstance.getClass();
List<BeanOverrideHandler> handlers = BeanOverrideHandler.forTestClass(testClass);
if (!handlers.isEmpty()) { if (!handlers.isEmpty()) {
Object testInstance = testContext.getTestInstance();
ApplicationContext applicationContext = testContext.getApplicationContext(); ApplicationContext applicationContext = testContext.getApplicationContext();
Assert.state(applicationContext.containsBean(BeanOverrideRegistry.BEAN_NAME), () -> """ Assert.state(applicationContext.containsBean(BeanOverrideRegistry.BEAN_NAME), () -> """

6
spring-test/src/test/java/org/springframework/test/context/bean/override/convention/TestBeanByNameLookupIntegrationTests.java → spring-test/src/test/java/org/springframework/test/context/bean/override/convention/TestBeanByNameLookupTestClassScopedExtensionContextIntegrationTests.java

@ -19,6 +19,7 @@ package org.springframework.test.context.bean.override.convention;
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -28,14 +29,15 @@ import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
/** /**
* Integration tests for {@link TestBean} that use by-name lookup. * Integration tests for {@link TestBean} that use by-name lookup with test class
* {@link ExtensionContextScope}.
* *
* @author Simon Baslé * @author Simon Baslé
* @author Sam Brannen * @author Sam Brannen
* @since 6.2 * @since 6.2
*/ */
@SpringJUnitConfig @SpringJUnitConfig
public class TestBeanByNameLookupIntegrationTests { public class TestBeanByNameLookupTestClassScopedExtensionContextIntegrationTests {
@TestBean(name = "field") @TestBean(name = "field")
String field; String field;

205
spring-test/src/test/java/org/springframework/test/context/bean/override/convention/TestBeanByNameLookupTestMethodScopedExtensionContextIntegrationTests.java

@ -0,0 +1,205 @@
/*
* 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.bean.override.convention;
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;
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
* {@link ExtensionContextScope#TEST_METHOD}.
*
* @author Simon Baslé
* @author Sam Brannen
* @since 6.2.13
*/
public class TestBeanByNameLookupTestMethodScopedExtensionContextIntegrationTests {
@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));
}
@SpringJUnitConfig
public static class TestCase {
@TestBean(name = "field")
String field;
@TestBean(name = "methodRenamed1", methodName = "field")
String methodRenamed1;
static String field() {
return "fieldOverride";
}
static String nestedField() {
return "nestedFieldOverride";
}
@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");
}
@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 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 @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 TestBeanFactoryMethodInEnclosingClassTestCase {
@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 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");
}
}
}
}
@Configuration(proxyBeanMethods = false)
static class Config {
@Bean("field")
String bean1() {
return "prod";
}
@Bean("nestedField")
String bean2() {
return "nestedProd";
}
@Bean("methodRenamed1")
String bean3() {
return "Prod";
}
@Bean("methodRenamed2")
String bean4() {
return "NestedProd";
}
}
}

6
spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanByNameLookupIntegrationTests.java → spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanByNameLookupTestClassScopedExtensionContextIntegrationTests.java

@ -19,6 +19,7 @@ package org.springframework.test.context.bean.override.mockito;
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
@ -33,14 +34,15 @@ import org.springframework.test.mockito.MockitoAssertions;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
/** /**
* Integration tests for {@link MockitoBean} that use by-name lookup. * Integration tests for {@link MockitoBean} that use by-name lookup with test class
* {@link ExtensionContextScope}.
* *
* @author Simon Baslé * @author Simon Baslé
* @author Sam Brannen * @author Sam Brannen
* @since 6.2 * @since 6.2
*/ */
@SpringJUnitConfig @SpringJUnitConfig
public class MockitoBeanByNameLookupIntegrationTests { public class MockitoBeanByNameLookupTestClassScopedExtensionContextIntegrationTests {
@MockitoBean("field") @MockitoBean("field")
ExampleService field; ExampleService field;

164
spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoBeanByNameLookupTestMethodScopedExtensionContextIntegrationTests.java

@ -0,0 +1,164 @@
/*
* 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.bean.override.mockito;
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;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.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
* {@link ExtensionContextScope#TEST_METHOD}.
*
* @author Simon Baslé
* @author Sam Brannen
* @since 6.2.13
*/
public class MockitoBeanByNameLookupTestMethodScopedExtensionContextIntegrationTests {
@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));
}
@SpringJUnitConfig
public static class TestCase {
@MockitoBean("field")
ExampleService field;
@MockitoBean("nonExistingBean")
ExampleService nonExisting;
@Test
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 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);
}
}
}
@Configuration(proxyBeanMethods = false)
static class Config {
@Bean("field")
ExampleService bean1() {
return new RealExampleService("Hello Field");
}
@Bean("nestedField")
ExampleService bean2() {
return new RealExampleService("Hello Nested Field");
}
}
}

8
spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanByNameLookupIntegrationTests.java → spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanByNameLookupTestClassScopedExtensionContextIntegrationTests.java

@ -19,6 +19,7 @@ package org.springframework.test.context.bean.override.mockito;
import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
@ -27,21 +28,22 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.bean.override.example.ExampleService; 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.example.RealExampleService;
import org.springframework.test.context.bean.override.mockito.MockitoSpyBeanByNameLookupIntegrationTests.Config; import org.springframework.test.context.bean.override.mockito.MockitoSpyBeanByNameLookupTestClassScopedExtensionContextIntegrationTests.Config;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import org.springframework.test.mockito.MockitoAssertions; import org.springframework.test.mockito.MockitoAssertions;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
/** /**
* Integration tests for {@link MockitoSpyBean} that use by-name lookup. * Integration tests for {@link MockitoSpyBean} that use by-name lookup with test class
* {@link ExtensionContextScope}.
* *
* @author Simon Baslé * @author Simon Baslé
* @author Sam Brannen * @author Sam Brannen
* @since 6.2 * @since 6.2
*/ */
@SpringJUnitConfig(Config.class) @SpringJUnitConfig(Config.class)
public class MockitoSpyBeanByNameLookupIntegrationTests { public class MockitoSpyBeanByNameLookupTestClassScopedExtensionContextIntegrationTests {
@MockitoSpyBean("field1") @MockitoSpyBean("field1")
ExampleService field; ExampleService field;

126
spring-test/src/test/java/org/springframework/test/context/bean/override/mockito/MockitoSpyBeanByNameLookupTestMethodScopedExtensionContextIntegrationTests.java

@ -0,0 +1,126 @@
/*
* 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.bean.override.mockito;
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;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
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.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
* {@link ExtensionContextScope#TEST_METHOD}.
*
* @author Simon Baslé
* @author Sam Brannen
* @since 6.2.13
*/
public class MockitoSpyBeanByNameLookupTestMethodScopedExtensionContextIntegrationTests {
@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));
}
@SpringJUnitConfig(Config.class)
public static class TestCase {
@MockitoSpyBean("field1")
ExampleService field;
@Test
void fieldHasOverride(ApplicationContext ctx) {
assertThat(ctx.getBean("field1"))
.isInstanceOf(ExampleService.class)
.satisfies(MockitoAssertions::assertIsSpy)
.isSameAs(field);
assertThat(field.greeting()).isEqualTo("bean1");
}
@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");
}
}
}
@Configuration(proxyBeanMethods = false)
static class Config {
@Bean("field1")
ExampleService bean1() {
return new RealExampleService("bean1");
}
@Bean("field2")
ExampleService bean2() {
return new RealExampleService("bean2");
}
}
}

13
spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ActiveProfilesNestedTests.java → spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ActiveProfilesTestClassScopedExtensionContextNestedTests.java

@ -20,6 +20,7 @@ import java.util.List;
import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -30,7 +31,7 @@ import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.NestedTestConfiguration; import org.springframework.test.context.NestedTestConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import org.springframework.test.context.junit.jupiter.nested.ActiveProfilesNestedTests.Config1; import org.springframework.test.context.junit.jupiter.nested.ActiveProfilesTestClassScopedExtensionContextNestedTests.Config1;
import static org.assertj.core.api.Assertions.assertThat; 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.INHERIT;
@ -39,7 +40,8 @@ import static org.springframework.test.context.NestedTestConfiguration.Enclosing
/** /**
* Integration tests that verify support for {@code @Nested} test classes using * Integration tests that verify support for {@code @Nested} test classes using
* {@link ActiveProfiles @ActiveProfiles} in conjunction with the * {@link ActiveProfiles @ActiveProfiles} in conjunction with the
* {@link SpringExtension} in a JUnit Jupiter environment. * {@link SpringExtension} in a JUnit Jupiter environment with test class
* {@link ExtensionContextScope}.
* *
* @author Sam Brannen * @author Sam Brannen
* @since 5.3 * @since 5.3
@ -47,7 +49,7 @@ import static org.springframework.test.context.NestedTestConfiguration.Enclosing
@SpringJUnitConfig(Config1.class) @SpringJUnitConfig(Config1.class)
@ActiveProfiles("1") @ActiveProfiles("1")
@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default @NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default
class ActiveProfilesNestedTests { class ActiveProfilesTestClassScopedExtensionContextNestedTests {
@Autowired @Autowired
List<String> strings; List<String> strings;
@ -69,8 +71,9 @@ class ActiveProfilesNestedTests {
@Test @Test
void test() { void test() {
assertThat(strings).containsExactlyInAnyOrder("X", "A1"); assertThat(strings)
assertThat(this.localStrings).containsExactlyInAnyOrder("X", "A1"); .isEqualTo(this.localStrings)
.containsExactlyInAnyOrder("X", "A1");
} }
} }

236
spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ActiveProfilesTestMethodScopedExtensionContextNestedTests.java

@ -0,0 +1,236 @@
/*
* 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 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;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
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.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;
/**
* Integration tests that verify support for {@code @Nested} test classes using
* {@link ActiveProfiles @ActiveProfiles} in conjunction with the
* {@link SpringExtension} in a JUnit Jupiter environment with
* {@link ExtensionContextScope#TEST_METHOD}.
*
* @author Sam Brannen
* @since 6.2.13
*/
class ActiveProfilesTestMethodScopedExtensionContextNestedTests {
@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));
}
@SpringJUnitConfig(Config1.class)
@ActiveProfiles("1")
@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default
static class TestCase {
@Autowired
List<String> strings;
@Test
void test() {
assertThat(this.strings).containsExactlyInAnyOrder("X", "A1");
}
@Nested
@NestedTestConfiguration(INHERIT)
class InheritedConfigTestCase {
@Autowired
List<String> localStrings;
@Test
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");
}
@Nested
@NestedTestConfiguration(OVERRIDE)
@SpringJUnitConfig({ Config1.class, Config2.class, Config3.class })
@ActiveProfiles("3")
class DoubleNestedWithOverriddenConfigTestCase {
@Autowired
List<String> localStrings;
@Test
void test() {
assertThat(strings)
.isEqualTo(this.localStrings)
.containsExactlyInAnyOrder("X", "Y", "Z", "A3");
}
@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");
}
}
}
}
}
// -------------------------------------------------------------------------
@Configuration
static class Config1 {
@Bean
String x() {
return "X";
}
@Bean
@Profile("1")
String a1() {
return "A1";
}
}
@Configuration
static class Config2 {
@Bean
String y() {
return "Y";
}
@Bean
@Profile("2")
String a2() {
return "A2";
}
}
@Configuration
static class Config3 {
@Bean
String z() {
return "Z";
}
@Bean
@Profile("3")
String a3() {
return "A3";
}
}
@ActiveProfiles("2")
interface TestInterface {
}
}

14
spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ConstructorInjectionNestedTests.java → spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ConstructorInjectionTestClassScopedExtensionContextNestedTests.java

@ -19,6 +19,7 @@ package org.springframework.test.context.junit.jupiter.nested;
import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo; import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
@ -28,28 +29,29 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.NestedTestConfiguration; import org.springframework.test.context.NestedTestConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import org.springframework.test.context.junit.jupiter.nested.ConstructorInjectionNestedTests.TopLevelConfig; import org.springframework.test.context.junit.jupiter.nested.ConstructorInjectionTestClassScopedExtensionContextNestedTests.TopLevelConfig;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.OVERRIDE; import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.OVERRIDE;
/** /**
* Integration tests that verify support for {@code @Nested} test classes in conjunction * Integration tests that verify support for {@code @Nested} test classes in conjunction
* with the {@link SpringExtension} in a JUnit Jupiter environment ... when using * with the {@link SpringExtension} in a JUnit Jupiter environment with test class
* constructor injection as opposed to field injection (see SPR-16653). * {@link ExtensionContextScope} ... when using constructor injection as opposed
* to field injection (see SPR-16653).
* *
* @author Sam Brannen * @author Sam Brannen
* @since 5.0.5 * @since 5.0.5
* @see ContextConfigurationNestedTests * @see ContextConfigurationTestClassScopedExtensionContextNestedTests
* @see org.springframework.test.context.junit4.nested.NestedTestsWithSpringRulesTests * @see org.springframework.test.context.junit4.nested.NestedTestsWithSpringRulesTests
*/ */
@SpringJUnitConfig(TopLevelConfig.class) @SpringJUnitConfig(TopLevelConfig.class)
@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default @NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default
class ConstructorInjectionNestedTests { class ConstructorInjectionTestClassScopedExtensionContextNestedTests {
final String foo; final String foo;
ConstructorInjectionNestedTests(TestInfo testInfo, @Autowired String foo) { ConstructorInjectionTestClassScopedExtensionContextNestedTests(TestInfo testInfo, @Autowired String foo) {
this.foo = foo; this.foo = foo;
} }

173
spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ConstructorInjectionTestMethodScopedExtensionContextNestedTests.java

@ -0,0 +1,173 @@
/*
* 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.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;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.NestedTestConfiguration;
import org.springframework.test.context.junit.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.OVERRIDE;
/**
* Integration tests that verify support for {@code @Nested} test classes in conjunction
* with the {@link SpringExtension} in a JUnit Jupiter environment with
* {@link ExtensionContextScope#TEST_METHOD} ... when using constructor injection
* as opposed to field injection (see SPR-16653).
*
* @author Sam Brannen
* @since 6.2.13
* @see ContextConfigurationTestClassScopedExtensionContextNestedTests
* @see org.springframework.test.context.junit4.nested.NestedTestsWithSpringRulesTests
*/
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));
}
@SpringJUnitConfig(TopLevelConfig.class)
@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default
static class TestCase {
final String foo;
TestCase(TestInfo testInfo, @Autowired String foo) {
this.foo = foo;
}
@Test
void topLevelTest() {
assertThat(foo).isEqualTo("foo");
}
@Nested
@SpringJUnitConfig(NestedConfig.class)
class AutowiredConstructorTestCase {
final String bar;
@Autowired
AutowiredConstructorTestCase(String bar) {
this.bar = bar;
}
@Test
void nestedTest() {
assertThat(foo).isEqualTo("bar");
assertThat(bar).isEqualTo("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");
}
}
@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");
}
}
@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);
}
}
}
// -------------------------------------------------------------------------
@Configuration
static class TopLevelConfig {
@Bean
String foo() {
return "foo";
}
}
@Configuration
static class NestedConfig {
@Bean
String bar() {
return "bar";
}
}
}

10
spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextConfigurationNestedTests.java → spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextConfigurationTestClassScopedExtensionContextNestedTests.java

@ -18,6 +18,7 @@ package org.springframework.test.context.junit.jupiter.nested;
import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
@ -27,7 +28,7 @@ import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.NestedTestConfiguration; import org.springframework.test.context.NestedTestConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import org.springframework.test.context.junit.jupiter.nested.ContextConfigurationNestedTests.TopLevelConfig; import org.springframework.test.context.junit.jupiter.nested.ContextConfigurationTestClassScopedExtensionContextNestedTests.TopLevelConfig;
import static org.assertj.core.api.Assertions.assertThat; 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.INHERIT;
@ -36,16 +37,17 @@ import static org.springframework.test.context.NestedTestConfiguration.Enclosing
/** /**
* Integration tests that verify support for {@code @Nested} test classes using * Integration tests that verify support for {@code @Nested} test classes using
* {@link ContextConfiguration @ContextConfiguration} in conjunction with the * {@link ContextConfiguration @ContextConfiguration} in conjunction with the
* {@link SpringExtension} in a JUnit Jupiter environment. * {@link SpringExtension} in a JUnit Jupiter environment with test class
* {@link ExtensionContextScope}.
* *
* @author Sam Brannen * @author Sam Brannen
* @since 5.0 * @since 5.0
* @see ConstructorInjectionNestedTests * @see ConstructorInjectionTestClassScopedExtensionContextNestedTests
* @see org.springframework.test.context.junit4.nested.NestedTestsWithSpringRulesTests * @see org.springframework.test.context.junit4.nested.NestedTestsWithSpringRulesTests
*/ */
@SpringJUnitConfig(TopLevelConfig.class) @SpringJUnitConfig(TopLevelConfig.class)
@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default @NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default
class ContextConfigurationNestedTests { class ContextConfigurationTestClassScopedExtensionContextNestedTests {
private static final String FOO = "foo"; private static final String FOO = "foo";
private static final String BAR = "bar"; private static final String BAR = "bar";

234
spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextConfigurationTestMethodScopedExtensionContextNestedTests.java

@ -0,0 +1,234 @@
/*
* 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.extension.TestInstantiationAwareExtension.ExtensionContextScope;
import org.junit.platform.testkit.engine.EngineTestKit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
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.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;
/**
* Integration tests that verify support for {@code @Nested} test classes using
* {@link ContextConfiguration @ContextConfiguration} in conjunction with the
* {@link SpringExtension} in a JUnit Jupiter environment with
* {@link ExtensionContextScope#TEST_METHOD}.
*
* @author Sam Brannen
* @since 6.2.13
* @see ConstructorInjectionTestClassScopedExtensionContextNestedTests
* @see org.springframework.test.context.junit4.nested.NestedTestsWithSpringRulesTests
*/
class ContextConfigurationTestMethodScopedExtensionContextNestedTests {
private static final String FOO = "foo";
private static final String BAR = "bar";
private static final String BAZ = "baz";
@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));
}
@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";
@Autowired(required = false)
@Qualifier("foo")
String foo;
@Test
void topLevelTest() {
assertThat(foo).isEqualTo(FOO);
}
@Nested
@SpringJUnitConfig(NestedConfig.class)
class NestedTestCase {
@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 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 {
@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 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);
}
}
}
}
}
// -------------------------------------------------------------------------
@Configuration
static class TopLevelConfig {
@Bean
String foo() {
return FOO;
}
}
@Configuration
static class NestedConfig {
@Bean
String bar() {
return BAR;
}
}
@Configuration
static class TestInterfaceConfig {
@Bean
String baz() {
return BAZ;
}
}
@ContextConfiguration(classes = TestInterfaceConfig.class)
interface TestInterface {
}
}

14
spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextHierarchyNestedTests.java → spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextHierarchyTestClassScopedExtensionContextNestedTests.java

@ -19,6 +19,7 @@ package org.springframework.test.context.junit.jupiter.nested;
import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
@ -30,7 +31,7 @@ import org.springframework.test.context.ContextHierarchy;
import org.springframework.test.context.NestedTestConfiguration; import org.springframework.test.context.NestedTestConfiguration;
import org.springframework.test.context.aot.DisabledInAotMode; import org.springframework.test.context.aot.DisabledInAotMode;
import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.junit.jupiter.nested.ContextHierarchyNestedTests.ParentConfig; import org.springframework.test.context.junit.jupiter.nested.ContextHierarchyTestClassScopedExtensionContextNestedTests.ParentConfig;
import static org.assertj.core.api.Assertions.assertThat; 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.INHERIT;
@ -39,7 +40,8 @@ import static org.springframework.test.context.NestedTestConfiguration.Enclosing
/** /**
* Integration tests that verify support for {@code @Nested} test classes using * Integration tests that verify support for {@code @Nested} test classes using
* {@link ContextHierarchy @ContextHierarchy} in conjunction with the * {@link ContextHierarchy @ContextHierarchy} in conjunction with the
* {@link SpringExtension} in a JUnit Jupiter environment. * {@link SpringExtension} in a JUnit Jupiter environment with test class
* {@link ExtensionContextScope}.
* *
* @author Sam Brannen * @author Sam Brannen
* @since 5.3 * @since 5.3
@ -48,7 +50,7 @@ import static org.springframework.test.context.NestedTestConfiguration.Enclosing
@ContextHierarchy(@ContextConfiguration(classes = ParentConfig.class)) @ContextHierarchy(@ContextConfiguration(classes = ParentConfig.class))
@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default @NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default
@DisabledInAotMode("@ContextHierarchy is not supported in AOT") @DisabledInAotMode("@ContextHierarchy is not supported in AOT")
class ContextHierarchyNestedTests { class ContextHierarchyTestClassScopedExtensionContextNestedTests {
private static final String FOO = "foo"; private static final String FOO = "foo";
private static final String BAR = "bar"; private static final String BAR = "bar";
@ -97,7 +99,7 @@ class ContextHierarchyNestedTests {
@Nested @Nested
@NestedTestConfiguration(INHERIT) @NestedTestConfiguration(INHERIT)
@ContextConfiguration(classes = Child1Config.class) @ContextConfiguration(classes = Child1Config.class)
class NestedTestCaseWithInheritedConfigTests { class NestedInheritedCfgTests {
@Autowired @Autowired
String bar; String bar;
@ -125,7 +127,7 @@ class ContextHierarchyNestedTests {
@ContextConfiguration(classes = ParentConfig.class), @ContextConfiguration(classes = ParentConfig.class),
@ContextConfiguration(classes = Child2Config.class) @ContextConfiguration(classes = Child2Config.class)
}) })
class DoubleNestedTestCaseWithOverriddenConfigTests { class DoubleNestedOverriddenCfgTests {
@Autowired @Autowired
String bar; String bar;
@ -146,7 +148,7 @@ class ContextHierarchyNestedTests {
@Nested @Nested
@NestedTestConfiguration(INHERIT) @NestedTestConfiguration(INHERIT)
class TripleNestedWithInheritedConfigAndTestInterfaceTests implements TestInterface { class TripleNestedInheritedCfgAndTestInterfaceTests implements TestInterface {
@Autowired @Autowired
@Qualifier("foo") @Qualifier("foo")

261
spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/ContextHierarchyTestMethodScopedExtensionContextNestedTests.java

@ -0,0 +1,261 @@
/*
* 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.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;
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.ContextHierarchy;
import org.springframework.test.context.NestedTestConfiguration;
import org.springframework.test.context.aot.DisabledInAotMode;
import org.springframework.test.context.junit.jupiter.SpringExtension;
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;
/**
* Integration tests that verify support for {@code @Nested} test classes using
* {@link ContextHierarchy @ContextHierarchy} in conjunction with the
* {@link SpringExtension} in a JUnit Jupiter environment with
* {@link ExtensionContextScope#TEST_METHOD}.
*
* @author Sam Brannen
* @since 6.2.13
*/
class ContextHierarchyTestMethodScopedExtensionContextNestedTests {
private static final String FOO = "foo";
private static final String BAR = "bar";
private static final String BAZ = "baz";
private static final String QUX = "qux";
@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));
}
@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 {
@Autowired
String foo;
@Autowired
ApplicationContext context;
@Test
void topLevelTest() {
assertThat(this.context).as("local ApplicationContext").isNotNull();
assertThat(this.context.getParent()).as("parent ApplicationContext").isNull();
assertThat(foo).isEqualTo(FOO);
}
@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 {
@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
@NestedTestConfiguration(OVERRIDE)
@ContextHierarchy({
@ContextConfiguration(classes = ParentConfig.class),
@ContextConfiguration(classes = Child2Config.class)
})
class DoubleNestedOverriddenCfgTestCase {
@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(foo).as("foo")
.isEqualTo(this.context.getBean("foo", String.class))
.isEqualTo(QUX + 2);
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);
}
}
}
}
}
// -------------------------------------------------------------------------
@Configuration
static class ParentConfig {
@Bean
String foo() {
return FOO;
}
}
@Configuration
static class Child1Config {
@Bean
String foo() {
return QUX + 1;
}
@Bean
String bar() {
return BAZ + 1;
}
}
@Configuration
static class Child2Config {
@Bean
String foo() {
return QUX + 2;
}
@Bean
String bar() {
return BAZ + 2;
}
}
@Configuration
static class NestedConfig {
@Bean
String bar() {
return BAR;
}
}
@Configuration
static class TestInterfaceConfig {
@Bean
String foo() {
return "test interface";
}
}
@ContextConfiguration(classes = TestInterfaceConfig.class)
interface TestInterface {
}
}

8
spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestConstructorNestedTests.java → spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestConstructorTestClassScopedExtensionContextNestedTests.java

@ -18,6 +18,7 @@ package org.springframework.test.context.junit.jupiter.nested;
import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
@ -36,7 +37,8 @@ import static org.springframework.test.context.TestConstructor.AutowireMode.ANNO
/** /**
* Integration tests that verify support for {@code @Nested} test classes using * Integration tests that verify support for {@code @Nested} test classes using
* {@link TestConstructor @TestConstructor} in conjunction with the * {@link TestConstructor @TestConstructor} in conjunction with the
* {@link SpringExtension} in a JUnit Jupiter environment. * {@link SpringExtension} in a JUnit Jupiter environment with test class
* {@link ExtensionContextScope}.
* *
* @author Sam Brannen * @author Sam Brannen
* @since 5.3 * @since 5.3
@ -44,9 +46,9 @@ import static org.springframework.test.context.TestConstructor.AutowireMode.ANNO
@SpringJUnitConfig @SpringJUnitConfig
@TestConstructor(autowireMode = ALL) @TestConstructor(autowireMode = ALL)
@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default @NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default
class TestConstructorNestedTests { class TestConstructorTestClassScopedExtensionContextNestedTests {
TestConstructorNestedTests(String text) { TestConstructorTestClassScopedExtensionContextNestedTests(String text) {
assertThat(text).isEqualTo("enigma"); assertThat(text).isEqualTo("enigma");
} }

190
spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestConstructorTestMethodScopedExtensionContextNestedTests.java

@ -0,0 +1,190 @@
/*
* 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.extension.TestInstantiationAwareExtension.ExtensionContextScope;
import org.junit.platform.testkit.engine.EngineTestKit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
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.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;
import static org.springframework.test.context.TestConstructor.AutowireMode.ANNOTATED;
/**
* Integration tests that verify support for {@code @Nested} test classes using
* {@link TestConstructor @TestConstructor} in conjunction with the
* {@link SpringExtension} in a JUnit Jupiter environment with
* {@link ExtensionContextScope#TEST_METHOD}.
*
* @author Sam Brannen
* @since 6.2.13
*/
class TestConstructorTestMethodScopedExtensionContextNestedTests {
@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));
}
@SpringJUnitConfig(Config.class)
@TestConstructor(autowireMode = ALL)
@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default
static class TestCase {
TestCase(String text) {
assertThat(text).isEqualTo("enigma");
}
@Test
void test() {
}
@Nested
@SpringJUnitConfig(Config.class)
@TestConstructor(autowireMode = ANNOTATED)
class ConfigOverriddenByDefaultTestCase {
@Autowired
ConfigOverriddenByDefaultTestCase(String text) {
assertThat(text).isEqualTo("enigma");
}
@Test
void test() {
}
}
@Nested
@NestedTestConfiguration(INHERIT)
class InheritedConfigTestCase {
InheritedConfigTestCase(String text) {
assertThat(text).isEqualTo("enigma");
}
@Test
void test() {
}
@Nested
class DoubleNestedWithImplicitlyInheritedConfigTestCase {
DoubleNestedWithImplicitlyInheritedConfigTestCase(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 {
DoubleNestedWithOverriddenConfigTestCase(@Autowired 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() {
}
}
}
}
}
// -------------------------------------------------------------------------
@Configuration
static class Config {
@Bean
String text() {
return "enigma";
}
}
@TestConstructor(autowireMode = ALL)
interface TestInterface {
}
}

18
spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestPropertySourceNestedTests.java → spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestPropertySourceTestClassScopedExtensionContextNestedTests.java

@ -18,6 +18,7 @@ package org.springframework.test.context.junit.jupiter.nested;
import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.TestInstantiationAwareExtension.ExtensionContextScope;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
@ -26,7 +27,7 @@ import org.springframework.test.context.NestedTestConfiguration;
import org.springframework.test.context.TestPropertySource; import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import org.springframework.test.context.junit.jupiter.nested.TestPropertySourceNestedTests.Config; import org.springframework.test.context.junit.jupiter.nested.TestPropertySourceTestClassScopedExtensionContextNestedTests.Config;
import static org.assertj.core.api.Assertions.assertThat; 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.INHERIT;
@ -35,7 +36,8 @@ import static org.springframework.test.context.NestedTestConfiguration.Enclosing
/** /**
* Integration tests that verify support for {@code @Nested} test classes using * Integration tests that verify support for {@code @Nested} test classes using
* {@link TestPropertySource @TestPropertySource} in conjunction with the * {@link TestPropertySource @TestPropertySource} in conjunction with the
* {@link SpringExtension} in a JUnit Jupiter environment. * {@link SpringExtension} in a JUnit Jupiter environment with test class
* {@link ExtensionContextScope}.
* *
* @author Sam Brannen * @author Sam Brannen
* @since 5.3 * @since 5.3
@ -43,7 +45,7 @@ import static org.springframework.test.context.NestedTestConfiguration.Enclosing
@SpringJUnitConfig(Config.class) @SpringJUnitConfig(Config.class)
@TestPropertySource(properties = "p1 = v1") @TestPropertySource(properties = "p1 = v1")
@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default @NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default
class TestPropertySourceNestedTests { class TestPropertySourceTestClassScopedExtensionContextNestedTests {
@Autowired @Autowired
Environment env1; Environment env1;
@ -57,7 +59,7 @@ class TestPropertySourceNestedTests {
@Nested @Nested
@NestedTestConfiguration(INHERIT) @NestedTestConfiguration(INHERIT)
class InheritedConfigTests { class InheritedCfgTests {
@Autowired @Autowired
Environment env2; Environment env2;
@ -93,7 +95,7 @@ class TestPropertySourceNestedTests {
@NestedTestConfiguration(INHERIT) @NestedTestConfiguration(INHERIT)
@TestPropertySource(properties = "p2a = v2a") @TestPropertySource(properties = "p2a = v2a")
@TestPropertySource(properties = "p2b = v2b") @TestPropertySource(properties = "p2b = v2b")
class InheritedAndExtendedConfigTests { class InheritedAndExtendedCfgTests {
@Autowired @Autowired
Environment env2; Environment env2;
@ -113,7 +115,7 @@ class TestPropertySourceNestedTests {
@NestedTestConfiguration(OVERRIDE) @NestedTestConfiguration(OVERRIDE)
@SpringJUnitConfig(Config.class) @SpringJUnitConfig(Config.class)
@TestPropertySource(properties = "p3 = v3") @TestPropertySource(properties = "p3 = v3")
class L3WithOverriddenConfigTests { class L3OverriddenCfgTests {
@Autowired @Autowired
Environment env3; Environment env3;
@ -136,7 +138,7 @@ class TestPropertySourceNestedTests {
@Nested @Nested
@NestedTestConfiguration(INHERIT) @NestedTestConfiguration(INHERIT)
@TestPropertySource(properties = {"p3 = v34", "p4 = v4"}, inheritProperties = false) @TestPropertySource(properties = {"p3 = v34", "p4 = v4"}, inheritProperties = false)
class L4WithInheritedConfigButOverriddenTestPropertiesTests { class L4InheritedCfgButOverriddenTestPropsTests {
@Autowired @Autowired
Environment env4; Environment env4;
@ -161,7 +163,7 @@ class TestPropertySourceNestedTests {
} }
@Nested @Nested
class L5WithInheritedConfigAndTestInterfaceTests implements TestInterface { class L5InheritedCfgAndTestInterfaceTests implements TestInterface {
@Autowired @Autowired
Environment env5; Environment env5;

198
spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/TestPropertySourceTestMethodScopedExtensionContextNestedTests.java

@ -0,0 +1,198 @@
/*
* 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.extension.TestInstantiationAwareExtension.ExtensionContextScope;
import org.junit.platform.testkit.engine.EngineTestKit;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
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.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;
/**
* Integration tests that verify support for {@code @Nested} test classes using
* {@link TestPropertySource @TestPropertySource} in conjunction with the
* {@link SpringExtension} in a JUnit Jupiter environment with
* {@link ExtensionContextScope#TEST_METHOD}.
*
* @author Sam Brannen
* @since 6.2.13
*/
class TestPropertySourceTestMethodScopedExtensionContextNestedTests {
@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));
}
@SpringJUnitConfig(Config.class)
@TestPropertySource(properties = "p1 = v1")
@NestedTestConfiguration(OVERRIDE) // since INHERIT is now the global default
static class TestCase {
@Autowired
Environment env1;
@Test
void propertiesInEnvironment() {
assertThat(env1.getProperty("p1")).isEqualTo("v1");
}
@Nested
@NestedTestConfiguration(INHERIT)
class InheritedCfgTestCase {
@Autowired
Environment env2;
@Test
void propertiesInEnvironment() {
assertThat(env1).isSameAs(env2);
assertThat(env2.getProperty("p1")).isEqualTo("v1");
}
}
@Nested
@SpringJUnitConfig(Config.class)
@TestPropertySource(properties = "p2 = v2")
class ConfigOverriddenByDefaultTestCase {
@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 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");
}
@Nested
@NestedTestConfiguration(OVERRIDE)
@SpringJUnitConfig(Config.class)
@TestPropertySource(properties = "p3 = v3")
class L3OverriddenCfgTestCase {
@Autowired
Environment env3;
@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");
}
@Nested
@NestedTestConfiguration(INHERIT)
@TestPropertySource(properties = {"p3 = v34", "p4 = v4"}, inheritProperties = false)
class L4InheritedCfgButOverriddenTestPropertiesTestCase {
@Autowired
Environment env4;
@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");
}
}
}
}
}
}
// -------------------------------------------------------------------------
@Configuration
static class Config {
/* no user beans required for these tests */
}
@TestPropertySource(properties = { "foo = bar", "enigma: 42" })
interface TestInterface {
}
}

3
spring-test/src/test/java/org/springframework/test/context/junit/jupiter/nested/WebAppConfigurationNestedTests.java

@ -40,7 +40,8 @@ import static org.springframework.test.context.NestedTestConfiguration.Enclosing
* *
* @author Sam Brannen * @author Sam Brannen
* @since 5.0 * @since 5.0
* @see ConstructorInjectionNestedTests * @see ConstructorInjectionTestClassScopedExtensionContextNestedTests
* @see ConstructorInjectionTestMethodScopedExtensionContextNestedTests
* @see org.springframework.test.context.junit4.nested.NestedTestsWithSpringRulesTests * @see org.springframework.test.context.junit4.nested.NestedTestsWithSpringRulesTests
*/ */
@SpringJUnitWebConfig(Config.class) @SpringJUnitWebConfig(Config.class)

3
spring-test/src/test/java/org/springframework/test/context/junit4/nested/NestedTestsWithSpringRulesTests.java

@ -37,7 +37,8 @@ import static org.assertj.core.api.Assertions.assertThat;
* *
* @author Sam Brannen * @author Sam Brannen
* @since 5.0 * @since 5.0
* @see org.springframework.test.context.junit.jupiter.nested.ContextConfigurationNestedTests * @see org.springframework.test.context.junit.jupiter.nested.ContextConfigurationTestClassScopedExtensionContextNestedTests
* @see org.springframework.test.context.junit.jupiter.nested.ContextConfigurationTestMethodScopedExtensionContextNestedTests
*/ */
@RunWith(HierarchicalContextRunner.class) @RunWith(HierarchicalContextRunner.class)
@ContextConfiguration(classes = TopLevelConfig.class) @ContextConfiguration(classes = TopLevelConfig.class)

Loading…
Cancel
Save