Browse Source
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-35697pull/35718/head
32 changed files with 1632 additions and 748 deletions
@ -0,0 +1,68 @@
@@ -0,0 +1,68 @@
|
||||
/* |
||||
* Copyright 2002-present the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.test.context.junit.jupiter; |
||||
|
||||
import java.lang.annotation.Documented; |
||||
import java.lang.annotation.ElementType; |
||||
import java.lang.annotation.Inherited; |
||||
import java.lang.annotation.Retention; |
||||
import java.lang.annotation.RetentionPolicy; |
||||
import java.lang.annotation.Target; |
||||
|
||||
/** |
||||
* {@code @SpringExtensionConfig} is a type-level annotation that can be used to |
||||
* configure the behavior of the {@link SpringExtension}. |
||||
* |
||||
* <p>This annotation is only applicable to {@link org.junit.jupiter.api.Nested @Nested} |
||||
* test class hierarchies and should be applied to the top-level enclosing class
|
||||
* of a {@code @Nested} test class hierarchy. Consequently, there is no need to |
||||
* declare this annotation on a test class that does not contain {@code @Nested} |
||||
* test classes. |
||||
* |
||||
* <p>Note that |
||||
* {@link org.springframework.test.context.NestedTestConfiguration @NestedTestConfiguration} |
||||
* does not apply to this annotation: {@code @SpringExtensionConfig} will always be |
||||
* detected within a {@code @Nested} test class hierarchy, effectively disregarding |
||||
* any {@code @NestedTestConfiguration(OVERRIDE)} declarations. |
||||
* |
||||
* @author Sam Brannen |
||||
* @since 7.0 |
||||
* @see org.springframework.test.context.junit.jupiter.SpringExtension SpringExtension |
||||
* @see org.springframework.test.context.junit.jupiter.SpringJUnitConfig @SpringJUnitConfig |
||||
* @see org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig @SpringJUnitWebConfig |
||||
*/ |
||||
@Target(ElementType.TYPE) |
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@Documented |
||||
@Inherited |
||||
public @interface SpringExtensionConfig { |
||||
|
||||
/** |
||||
* Specify whether the {@link SpringExtension} should use a test-class scoped |
||||
* {@link org.junit.jupiter.api.extension.ExtensionContext ExtensionContext} |
||||
* within {@link org.junit.jupiter.api.Nested @Nested} test class hierarchies. |
||||
* |
||||
* <p>By default, the {@code SpringExtension} uses a test-method scoped |
||||
* {@code ExtensionContext}. Thus, there is no need to declare this annotation |
||||
* attribute with a value of {@code false}. |
||||
* |
||||
* @see SpringExtension |
||||
* @see SpringExtension#getTestInstantiationExtensionContextScope(org.junit.jupiter.api.extension.ExtensionContext) |
||||
*/ |
||||
boolean useTestClassScopedExtensionContext(); |
||||
|
||||
} |
||||
@ -0,0 +1,186 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 { |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue