Discover test config on enclosing classes for nested test classes
Prior to this commit (and since Spring Framework 5.0), Spring's integration with JUnit Jupiter supported detection of test configuration (e.g., @ContextConfiguration, etc.) on @Nested classes. However, if a @Nested class did not declare its own test configuration, Spring would not find the configuration from the enclosing class. This is in contrast to Spring's support for automatic inheritance of test configuration from superclasses. The only workaround was to copy-n-paste the entire annotation configuration from enclosing classes to nested tests classes, which is cumbersome and error prone. This commit introduces a new @NestedTestConfiguration annotation that allows one to choose the EnclosingConfiguration mode that Spring should use when searching for test configuration on a @Nested test class. Currently, the options are INHERIT or OVERRIDE, where the current default is OVERRIDE. Note, however, that the default mode will be changed to INHERIT in a subsequent commit. In addition, support will be added to configure the global default mode via the SpringProperties mechanism in order to allow development teams to revert to the behavior prior to Spring Framework 5.3. As of this commit, inheritance of the following annotations is honored when the EnclosingConfiguration mode is INHERIT. - @ContextConfiguration / @ContextHierarchy - @ActiveProfiles - @TestPropertySource / @TestPropertySources - @WebAppConfiguration - @TestConstructor - @BootstrapWith - @TestExecutionListeners - @DirtiesContext - @Transactional - @Rollback / @Commit This commit does NOT include support for inheriting the following annotations on enclosing classes. - @Sql / @SqlConfig / @SqlGroup In order to implement this feature, the search algorithms in MetaAnnotationUtils (and various other spring-test internals) have been enhanced to detect when annotations should be looked up on enclosing classes. Other parts of the ecosystem may find the new searchEnclosingClass() method in MetaAnnotationUtils useful to provide similar support. As a side effect of the changes in this commit, validation of user configuration in repeated @TestPropertySource declarations has been removed, but this may be reintroduced at a later date. Closes gh-19930
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,17 +18,33 @@ package org.springframework.test.context;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.Arguments;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import org.springframework.test.context.BootstrapUtilsTests.OuterClass.NestedWithInheritedBootstrapper;
|
||||
import org.springframework.test.context.BootstrapUtilsTests.OuterClass.NestedWithInheritedBootstrapper.DoubleNestedWithInheritedButOverriddenBootstrapper;
|
||||
import org.springframework.test.context.BootstrapUtilsTests.OuterClass.NestedWithInheritedBootstrapper.DoubleNestedWithOverriddenBootstrapper;
|
||||
import org.springframework.test.context.BootstrapUtilsTests.OuterClass.NestedWithInheritedBootstrapper.DoubleNestedWithOverriddenBootstrapper.TripleNestedWithInheritedBootstrapper;
|
||||
import org.springframework.test.context.BootstrapUtilsTests.OuterClass.NestedWithInheritedBootstrapper.DoubleNestedWithOverriddenBootstrapper.TripleNestedWithInheritedBootstrapperButLocalOverride;
|
||||
import org.springframework.test.context.BootstrapUtilsTests.WebAppConfigClass.NestedWithInheritedWebConfig;
|
||||
import org.springframework.test.context.BootstrapUtilsTests.WebAppConfigClass.NestedWithInheritedWebConfig.DoubleNestedWithImplicitlyInheritedWebConfig;
|
||||
import org.springframework.test.context.BootstrapUtilsTests.WebAppConfigClass.NestedWithInheritedWebConfig.DoubleNestedWithOverriddenWebConfig;
|
||||
import org.springframework.test.context.BootstrapUtilsTests.WebAppConfigClass.NestedWithInheritedWebConfig.DoubleNestedWithOverriddenWebConfig.TripleNestedWithInheritedOverriddenWebConfig;
|
||||
import org.springframework.test.context.BootstrapUtilsTests.WebAppConfigClass.NestedWithInheritedWebConfig.DoubleNestedWithOverriddenWebConfig.TripleNestedWithInheritedOverriddenWebConfigAndTestInterface;
|
||||
import org.springframework.test.context.support.DefaultTestContextBootstrapper;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.test.context.web.WebTestContextBootstrapper;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
import static org.junit.jupiter.params.provider.Arguments.arguments;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.springframework.test.context.BootstrapUtils.resolveTestContextBootstrapper;
|
||||
import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.INHERIT;
|
||||
import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.OVERRIDE;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link BootstrapUtils}.
|
||||
@@ -65,11 +81,6 @@ class BootstrapUtilsTests {
|
||||
assertBootstrapper(NonAnnotatedClass.class, DefaultTestContextBootstrapper.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolveTestContextBootstrapperForWebAppConfigurationAnnotatedClass() {
|
||||
assertBootstrapper(WebAppConfigurationAnnotatedClass.class, WebTestContextBootstrapper.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void resolveTestContextBootstrapperWithDirectBootstrapWithAnnotation() {
|
||||
assertBootstrapper(DirectBootstrapWithAnnotationClass.class, FooBootstrapper.class);
|
||||
@@ -90,6 +101,37 @@ class BootstrapUtilsTests {
|
||||
assertBootstrapper(DuplicateMetaAnnotatedBootstrapWithAnnotationClass.class, FooBootstrapper.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 5.3
|
||||
*/
|
||||
@ParameterizedTest(name = "{0}")
|
||||
@MethodSource
|
||||
void resolveTestContextBootstrapperInEnclosingClassHierarchy(String name, Class<?> testClass, Class<?> expectedBootstrapper) {
|
||||
assertBootstrapper(testClass, expectedBootstrapper);
|
||||
}
|
||||
|
||||
static Stream<Arguments> resolveTestContextBootstrapperInEnclosingClassHierarchy() {
|
||||
return Stream.of(//
|
||||
args(OuterClass.class, FooBootstrapper.class),//
|
||||
args(NestedWithInheritedBootstrapper.class, FooBootstrapper.class),//
|
||||
args(DoubleNestedWithInheritedButOverriddenBootstrapper.class, EnigmaBootstrapper.class),//
|
||||
args(DoubleNestedWithOverriddenBootstrapper.class, BarBootstrapper.class),//
|
||||
args(TripleNestedWithInheritedBootstrapper.class, BarBootstrapper.class),//
|
||||
args(TripleNestedWithInheritedBootstrapperButLocalOverride.class, EnigmaBootstrapper.class),//
|
||||
// @WebAppConfiguration and default bootstrapper
|
||||
args(WebAppConfigClass.class, WebTestContextBootstrapper.class),//
|
||||
args(NestedWithInheritedWebConfig.class, WebTestContextBootstrapper.class),//
|
||||
args(DoubleNestedWithImplicitlyInheritedWebConfig.class, WebTestContextBootstrapper.class),//
|
||||
args(DoubleNestedWithOverriddenWebConfig.class, DefaultTestContextBootstrapper.class),//
|
||||
args(TripleNestedWithInheritedOverriddenWebConfig.class, WebTestContextBootstrapper.class),//
|
||||
args(TripleNestedWithInheritedOverriddenWebConfigAndTestInterface.class, DefaultTestContextBootstrapper.class)//
|
||||
);
|
||||
}
|
||||
|
||||
private static Arguments args(Class<?> testClass, Class<? extends TestContextBootstrapper> expectedBootstrapper) {
|
||||
return arguments(testClass.getSimpleName(), testClass, expectedBootstrapper);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 5.1
|
||||
*/
|
||||
@@ -153,7 +195,62 @@ class BootstrapUtilsTests {
|
||||
@BootstrapWith(EnigmaBootstrapper.class)
|
||||
static class LocalDeclarationAndMetaAnnotatedBootstrapWithAnnotationClass {}
|
||||
|
||||
@WebAppConfiguration
|
||||
static class WebAppConfigurationAnnotatedClass {}
|
||||
@org.springframework.test.context.web.WebAppConfiguration
|
||||
static class WebAppConfigClass {
|
||||
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
class NestedWithInheritedWebConfig {
|
||||
|
||||
class DoubleNestedWithImplicitlyInheritedWebConfig {
|
||||
}
|
||||
|
||||
@NestedTestConfiguration(OVERRIDE)
|
||||
class DoubleNestedWithOverriddenWebConfig {
|
||||
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
@org.springframework.test.context.web.WebAppConfiguration
|
||||
class TripleNestedWithInheritedOverriddenWebConfig {
|
||||
}
|
||||
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
class TripleNestedWithInheritedOverriddenWebConfigAndTestInterface {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Intentionally not annotated with @WebAppConfiguration to ensure that
|
||||
// TripleNestedWithInheritedOverriddenWebConfigAndTestInterface is not
|
||||
// considered to be annotated with @WebAppConfiguration even though the
|
||||
// enclosing class for TestInterface is annotated with @WebAppConfiguration.
|
||||
interface TestInterface {
|
||||
}
|
||||
}
|
||||
|
||||
@BootWithFoo
|
||||
static class OuterClass {
|
||||
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
class NestedWithInheritedBootstrapper {
|
||||
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
@BootstrapWith(EnigmaBootstrapper.class)
|
||||
class DoubleNestedWithInheritedButOverriddenBootstrapper {
|
||||
}
|
||||
|
||||
@NestedTestConfiguration(OVERRIDE)
|
||||
@BootWithBar
|
||||
class DoubleNestedWithOverriddenBootstrapper {
|
||||
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
class TripleNestedWithInheritedBootstrapper {
|
||||
}
|
||||
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
@BootstrapWith(EnigmaBootstrapper.class)
|
||||
class TripleNestedWithInheritedBootstrapperButLocalOverride {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.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 org.springframework.test.context.junit.jupiter.nested.ActiveProfilesNestedTests.Config1;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 5.3
|
||||
*/
|
||||
@SpringJUnitConfig(Config1.class)
|
||||
@ActiveProfiles("1")
|
||||
class ActiveProfilesNestedTests {
|
||||
|
||||
@Autowired
|
||||
List<String> strings;
|
||||
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
assertThat(this.strings).containsExactlyInAnyOrder("X", "A1");
|
||||
}
|
||||
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
class InheritedConfigTests {
|
||||
|
||||
@Autowired
|
||||
List<String> localStrings;
|
||||
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
assertThat(strings).containsExactlyInAnyOrder("X", "A1");
|
||||
assertThat(this.localStrings).containsExactlyInAnyOrder("X", "A1");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@SpringJUnitConfig(Config2.class)
|
||||
@ActiveProfiles("2")
|
||||
class ConfigOverriddenByDefaultTests {
|
||||
|
||||
@Autowired
|
||||
List<String> localStrings;
|
||||
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
assertThat(strings).containsExactlyInAnyOrder("X", "A1");
|
||||
assertThat(this.localStrings).containsExactlyInAnyOrder("Y", "A2");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
@ContextConfiguration(classes = Config2.class)
|
||||
@ActiveProfiles("2")
|
||||
class InheritedAndExtendedConfigTests {
|
||||
|
||||
@Autowired
|
||||
List<String> localStrings;
|
||||
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
assertThat(strings).containsExactlyInAnyOrder("X", "A1");
|
||||
assertThat(this.localStrings).containsExactlyInAnyOrder("X", "A1", "Y", "A2");
|
||||
}
|
||||
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(OVERRIDE)
|
||||
@SpringJUnitConfig({ Config1.class, Config2.class, Config3.class })
|
||||
@ActiveProfiles("3")
|
||||
class DoubleNestedWithOverriddenConfigTests {
|
||||
|
||||
@Autowired
|
||||
List<String> localStrings;
|
||||
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
assertThat(strings).containsExactlyInAnyOrder("X", "A1");
|
||||
assertThat(this.localStrings).containsExactlyInAnyOrder("X", "Y", "Z", "A3");
|
||||
}
|
||||
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
@ActiveProfiles(profiles = "2", inheritProfiles = false)
|
||||
class TripleNestedWithInheritedConfigButOverriddenProfilesTests {
|
||||
|
||||
@Autowired
|
||||
List<String> localStrings;
|
||||
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
assertThat(strings).containsExactlyInAnyOrder("X", "A1");
|
||||
assertThat(this.localStrings).containsExactlyInAnyOrder("X", "Y", "Z", "A2");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
class TripleNestedWithInheritedConfigAndTestInterfaceTests implements TestInterface {
|
||||
|
||||
@Autowired
|
||||
List<String> localStrings;
|
||||
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
assertThat(strings).containsExactlyInAnyOrder("X", "A1");
|
||||
assertThat(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 {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -28,7 +28,7 @@ import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.junit.SpringJUnitJupiterTestSuite;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
import org.springframework.test.context.junit.jupiter.nested.NestedTestsWithConstructorInjectionWithSpringAndJUnitJupiterTests.TopLevelConfig;
|
||||
import org.springframework.test.context.junit.jupiter.nested.ConstructorInjectionNestedTests.TopLevelConfig;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@@ -43,15 +43,15 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 5.0.5
|
||||
* @see NestedTestsWithSpringAndJUnitJupiterTests
|
||||
* @see ContextConfigurationNestedTests
|
||||
* @see org.springframework.test.context.junit4.nested.NestedTestsWithSpringRulesTests
|
||||
*/
|
||||
@SpringJUnitConfig(TopLevelConfig.class)
|
||||
class NestedTestsWithConstructorInjectionWithSpringAndJUnitJupiterTests {
|
||||
class ConstructorInjectionNestedTests {
|
||||
|
||||
final String foo;
|
||||
|
||||
NestedTestsWithConstructorInjectionWithSpringAndJUnitJupiterTests(TestInfo testInfo, @Autowired String foo) {
|
||||
ConstructorInjectionNestedTests(TestInfo testInfo, @Autowired String foo) {
|
||||
this.foo = foo;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.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 org.springframework.test.context.junit.jupiter.nested.ContextConfigurationNestedTests.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;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 5.0
|
||||
* @see ConstructorInjectionNestedTests
|
||||
* @see org.springframework.test.context.junit4.nested.NestedTestsWithSpringRulesTests
|
||||
*/
|
||||
@SpringJUnitConfig(TopLevelConfig.class)
|
||||
class ContextConfigurationNestedTests {
|
||||
|
||||
private static final String FOO = "foo";
|
||||
private static final String BAR = "bar";
|
||||
private static final String BAZ = "baz";
|
||||
|
||||
@Autowired
|
||||
String foo;
|
||||
|
||||
|
||||
@Test
|
||||
void topLevelTest() {
|
||||
assertThat(foo).isEqualTo(FOO);
|
||||
}
|
||||
|
||||
|
||||
@Nested
|
||||
@SpringJUnitConfig(NestedConfig.class)
|
||||
class NestedTests {
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
class NestedTestCaseWithInheritedConfigTests {
|
||||
|
||||
@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 DoubleNestedWithOverriddenConfigTests {
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
class TripleNestedWithInheritedConfigTests {
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
class TripleNestedWithInheritedConfigAndTestInterfaceTests implements TestInterface {
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@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 {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.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.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.context.junit.jupiter.nested.ContextHierarchyNestedTests.ParentConfig;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 5.3
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@ContextHierarchy(@ContextConfiguration(classes = ParentConfig.class))
|
||||
class ContextHierarchyNestedTests {
|
||||
|
||||
private static final String FOO = "foo";
|
||||
private static final String BAR = "bar";
|
||||
private static final String BAZ = "baz";
|
||||
private static final String QUX = "qux";
|
||||
|
||||
@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 NestedTests {
|
||||
|
||||
@Autowired
|
||||
String bar;
|
||||
|
||||
@Autowired
|
||||
ApplicationContext context;
|
||||
|
||||
|
||||
@Test
|
||||
void nestedTest() throws Exception {
|
||||
assertThat(this.context).as("local ApplicationContext").isNotNull();
|
||||
assertThat(this.context.getParent()).as("parent ApplicationContext").isNull();
|
||||
|
||||
// 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.bar).isEqualTo(BAR);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
@ContextConfiguration(classes = Child1Config.class)
|
||||
class NestedTestCaseWithInheritedConfigTests {
|
||||
|
||||
@Autowired
|
||||
String bar;
|
||||
|
||||
@Autowired
|
||||
ApplicationContext context;
|
||||
|
||||
|
||||
@Test
|
||||
void nestedTest() throws Exception {
|
||||
assertThat(this.context).as("local ApplicationContext").isNotNull();
|
||||
assertThat(this.context.getParent()).as("parent ApplicationContext").isNotNull();
|
||||
|
||||
// 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.bar).isEqualTo(BAZ + 1);
|
||||
assertThat(this.context.getBean("foo", String.class)).as("child foo").isEqualTo(QUX + 1);
|
||||
}
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(OVERRIDE)
|
||||
@ContextHierarchy({
|
||||
@ContextConfiguration(classes = ParentConfig.class),
|
||||
@ContextConfiguration(classes = Child2Config.class)
|
||||
})
|
||||
class DoubleNestedTestCaseWithOverriddenConfigTests {
|
||||
|
||||
@Autowired
|
||||
String bar;
|
||||
|
||||
@Autowired
|
||||
ApplicationContext context;
|
||||
|
||||
|
||||
@Test
|
||||
void nestedTest() throws Exception {
|
||||
assertThat(this.context).as("local ApplicationContext").isNotNull();
|
||||
assertThat(this.context.getParent()).as("parent ApplicationContext").isNotNull();
|
||||
|
||||
assertThat(foo).isEqualTo(FOO);
|
||||
assertThat(this.bar).isEqualTo(BAZ + 2);
|
||||
assertThat(this.context.getBean("foo", String.class)).as("child foo").isEqualTo(QUX + 2);
|
||||
}
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
class TripleNestedWithInheritedConfigAndTestInterfaceTests implements TestInterface {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("foo")
|
||||
String localFoo;
|
||||
|
||||
@Autowired
|
||||
String bar;
|
||||
|
||||
@Autowired
|
||||
ApplicationContext context;
|
||||
|
||||
|
||||
@Test
|
||||
void nestedTest() throws Exception {
|
||||
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).isEqualTo(FOO);
|
||||
assertThat(this.localFoo).isEqualTo("test interface");
|
||||
assertThat(this.bar).isEqualTo(BAZ + 2);
|
||||
assertThat(this.context.getParent().getBean("foo", String.class)).as("child foo").isEqualTo(QUX + 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 {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,95 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-2019 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.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.junit.SpringJUnitJupiterTestSuite;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
import org.springframework.test.context.junit.jupiter.nested.NestedTestsWithSpringAndJUnitJupiterTests.TopLevelConfig;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests that verify support for {@code @Nested} test classes
|
||||
* in conjunction with the {@link SpringExtension} in a JUnit Jupiter environment.
|
||||
*
|
||||
* <p>To run these tests in an IDE that does not have built-in support for the JUnit
|
||||
* Platform, simply run {@link SpringJUnitJupiterTestSuite} as a JUnit 4 test.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 5.0
|
||||
* @see NestedTestsWithConstructorInjectionWithSpringAndJUnitJupiterTests
|
||||
* @see org.springframework.test.context.junit4.nested.NestedTestsWithSpringRulesTests
|
||||
*/
|
||||
@SpringJUnitConfig(TopLevelConfig.class)
|
||||
class NestedTestsWithSpringAndJUnitJupiterTests {
|
||||
|
||||
@Autowired
|
||||
String foo;
|
||||
|
||||
|
||||
@Test
|
||||
void topLevelTest() {
|
||||
assertThat(foo).isEqualTo("foo");
|
||||
}
|
||||
|
||||
|
||||
@Nested
|
||||
@SpringJUnitConfig(NestedConfig.class)
|
||||
class NestedTests {
|
||||
|
||||
@Autowired
|
||||
String bar;
|
||||
|
||||
|
||||
@Test
|
||||
void nestedTest() throws Exception {
|
||||
// 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(bar).isEqualTo("bar");
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Configuration
|
||||
static class TopLevelConfig {
|
||||
|
||||
@Bean
|
||||
String foo() {
|
||||
return "foo";
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class NestedConfig {
|
||||
|
||||
@Bean
|
||||
String bar() {
|
||||
return "bar";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -45,7 +45,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
@SpringJUnitConfig(PopulatedSchemaDatabaseConfig.class)
|
||||
@Transactional
|
||||
@TestInstance(Lifecycle.PER_CLASS)
|
||||
class NestedTestsWithSqlScriptsAndJUnitJupiterTests {
|
||||
class SqlScriptNestedTests {
|
||||
|
||||
@Autowired
|
||||
JdbcTemplate jdbcTemplate;
|
||||
@@ -67,6 +67,10 @@ class NestedTestsWithSqlScriptsAndJUnitJupiterTests {
|
||||
}
|
||||
|
||||
@Nested
|
||||
// NOTE: the following @SpringJUnitConfig declaration must NOT be removed.
|
||||
// This was added before the TestContext framework looked up configuration
|
||||
// on enclosing classes for @Nested test classes. As such, this serves as a
|
||||
// regression test and cannot be changed.
|
||||
@SpringJUnitConfig(PopulatedSchemaDatabaseConfig.class)
|
||||
@Transactional
|
||||
class NestedTests {
|
||||
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.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.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.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 5.3
|
||||
*/
|
||||
@SpringJUnitConfig
|
||||
@TestConstructor(autowireMode = ALL)
|
||||
class TestConstructorNestedTests {
|
||||
|
||||
TestConstructorNestedTests(String text) {
|
||||
assertThat(text).isEqualTo("enigma");
|
||||
}
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
}
|
||||
|
||||
|
||||
@Nested
|
||||
@SpringJUnitConfig(Config.class)
|
||||
@TestConstructor(autowireMode = ANNOTATED)
|
||||
class ConfigOverriddenByDefaultTests {
|
||||
|
||||
@Autowired
|
||||
ConfigOverriddenByDefaultTests(String text) {
|
||||
assertThat(text).isEqualTo("enigma");
|
||||
}
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
class InheritedConfigTests {
|
||||
|
||||
InheritedConfigTests(String text) {
|
||||
assertThat(text).isEqualTo("enigma");
|
||||
}
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
}
|
||||
|
||||
|
||||
@Nested
|
||||
class DoubleNestedWithImplicitlyInheritedConfigTests {
|
||||
|
||||
DoubleNestedWithImplicitlyInheritedConfigTests(String text) {
|
||||
assertThat(text).isEqualTo("enigma");
|
||||
}
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
}
|
||||
|
||||
|
||||
@Nested
|
||||
class TripleNestedWithImplicitlyInheritedConfigTests {
|
||||
|
||||
TripleNestedWithImplicitlyInheritedConfigTests(String text) {
|
||||
assertThat(text).isEqualTo("enigma");
|
||||
}
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(OVERRIDE)
|
||||
@SpringJUnitConfig(Config.class)
|
||||
@TestConstructor(autowireMode = ANNOTATED)
|
||||
class DoubleNestedWithOverriddenConfigTests {
|
||||
|
||||
DoubleNestedWithOverriddenConfigTests(@Autowired String text) {
|
||||
assertThat(text).isEqualTo("enigma");
|
||||
}
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
}
|
||||
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
class TripleNestedWithInheritedConfigTests {
|
||||
|
||||
@Autowired
|
||||
TripleNestedWithInheritedConfigTests(String text) {
|
||||
assertThat(text).isEqualTo("enigma");
|
||||
}
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
class TripleNestedWithInheritedConfigAndTestInterfaceTests implements TestInterface {
|
||||
|
||||
TripleNestedWithInheritedConfigAndTestInterfaceTests(String text) {
|
||||
assertThat(text).isEqualTo("enigma");
|
||||
}
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Configuration
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
String text() {
|
||||
return "enigma";
|
||||
}
|
||||
}
|
||||
|
||||
@TestConstructor(autowireMode = ALL)
|
||||
interface TestInterface {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.NestedTestConfiguration;
|
||||
import org.springframework.test.context.TestContext;
|
||||
import org.springframework.test.context.TestExecutionListeners;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
import org.springframework.test.context.junit.jupiter.nested.TestExecutionListenersNestedTests.FooTestExecutionListener;
|
||||
import org.springframework.test.context.support.AbstractTestExecutionListener;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Integration tests that verify support for {@code @Nested} test classes using
|
||||
* {@link TestExecutionListeners @TestExecutionListeners} in conjunction with the
|
||||
* {@link SpringExtension} in a JUnit Jupiter environment.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 5.3
|
||||
*/
|
||||
@SpringJUnitConfig
|
||||
@TestExecutionListeners(FooTestExecutionListener.class)
|
||||
class TestExecutionListenersNestedTests {
|
||||
|
||||
private static final String FOO = "foo";
|
||||
private static final String BAR = "bar";
|
||||
private static final String BAZ = "baz";
|
||||
private static final String QUX = "qux";
|
||||
|
||||
private static final List<String> listeners = new ArrayList<>();
|
||||
|
||||
|
||||
@AfterEach
|
||||
void resetListeners() {
|
||||
listeners.clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
assertThat(listeners).containsExactly(FOO);
|
||||
}
|
||||
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
class InheritedConfigTests {
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
assertThat(listeners).containsExactly(FOO);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@SpringJUnitConfig(Config.class)
|
||||
@TestExecutionListeners(BarTestExecutionListener.class)
|
||||
class ConfigOverriddenByDefaultTests {
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
assertThat(listeners).containsExactly(BAR);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
@SpringJUnitConfig(Config.class)
|
||||
@TestExecutionListeners(BarTestExecutionListener.class)
|
||||
class InheritedAndExtendedConfigTests {
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
assertThat(listeners).containsExactly(FOO, BAR);
|
||||
}
|
||||
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(OVERRIDE)
|
||||
@SpringJUnitConfig(Config.class)
|
||||
@TestExecutionListeners(BazTestExecutionListener.class)
|
||||
class DoubleNestedWithOverriddenConfigTests {
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
assertThat(listeners).containsExactly(BAZ);
|
||||
}
|
||||
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
@TestExecutionListeners(listeners = BarTestExecutionListener.class, inheritListeners = false)
|
||||
class TripleNestedWithInheritedConfigButOverriddenListenersTests {
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
assertThat(listeners).containsExactly(BAR);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
class TripleNestedWithInheritedConfigAndTestInterfaceTests implements TestInterface {
|
||||
|
||||
@Test
|
||||
void test() {
|
||||
assertThat(listeners).containsExactly(BAZ, QUX);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Configuration
|
||||
static class Config {
|
||||
/* no user beans required for these tests */
|
||||
}
|
||||
|
||||
private static abstract class BaseTestExecutionListener extends AbstractTestExecutionListener {
|
||||
|
||||
protected abstract String name();
|
||||
|
||||
@Override
|
||||
public final void beforeTestClass(TestContext testContext) {
|
||||
listeners.add(name());
|
||||
}
|
||||
}
|
||||
|
||||
static class FooTestExecutionListener extends BaseTestExecutionListener {
|
||||
|
||||
@Override
|
||||
protected String name() {
|
||||
return FOO;
|
||||
}
|
||||
}
|
||||
|
||||
static class BarTestExecutionListener extends BaseTestExecutionListener {
|
||||
|
||||
@Override
|
||||
protected String name() {
|
||||
return BAR;
|
||||
}
|
||||
}
|
||||
|
||||
static class BazTestExecutionListener extends BaseTestExecutionListener {
|
||||
|
||||
@Override
|
||||
protected String name() {
|
||||
return BAZ;
|
||||
}
|
||||
}
|
||||
|
||||
static class QuxTestExecutionListener extends BaseTestExecutionListener {
|
||||
|
||||
@Override
|
||||
protected String name() {
|
||||
return QUX;
|
||||
}
|
||||
}
|
||||
|
||||
@TestExecutionListeners(QuxTestExecutionListener.class)
|
||||
interface TestInterface {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.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 org.springframework.test.context.junit.jupiter.nested.TestPropertySourceNestedTests.Config;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 5.3
|
||||
*/
|
||||
@SpringJUnitConfig(Config.class)
|
||||
@TestPropertySource(properties = "p1 = v1")
|
||||
class TestPropertySourceNestedTests {
|
||||
|
||||
@Autowired
|
||||
Environment env1;
|
||||
|
||||
|
||||
@Test
|
||||
void propertiesInEnvironment() {
|
||||
assertThat(env1.getProperty("p1")).isEqualTo("v1");
|
||||
}
|
||||
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
class InheritedConfigTests {
|
||||
|
||||
@Autowired
|
||||
Environment env2;
|
||||
|
||||
|
||||
@Test
|
||||
void propertiesInEnvironment() {
|
||||
assertThat(env1.getProperty("p1")).isEqualTo("v1");
|
||||
assertThat(env2.getProperty("p1")).isEqualTo("v1");
|
||||
assertThat(env1).isSameAs(env2);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@SpringJUnitConfig(Config.class)
|
||||
@TestPropertySource(properties = "p2 = v2")
|
||||
class ConfigOverriddenByDefaultTests {
|
||||
|
||||
@Autowired
|
||||
Environment env2;
|
||||
|
||||
|
||||
@Test
|
||||
void propertiesInEnvironment() {
|
||||
assertThat(env1.getProperty("p1")).isEqualTo("v1");
|
||||
assertThat(env1).isNotSameAs(env2);
|
||||
assertThat(env2.getProperty("p1")).isNull();
|
||||
assertThat(env2.getProperty("p2")).isEqualTo("v2");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
@TestPropertySource(properties = "p2a = v2a")
|
||||
@TestPropertySource(properties = "p2b = v2b")
|
||||
class InheritedAndExtendedConfigTests {
|
||||
|
||||
@Autowired
|
||||
Environment env2;
|
||||
|
||||
|
||||
@Test
|
||||
void propertiesInEnvironment() {
|
||||
assertThat(env1.getProperty("p1")).isEqualTo("v1");
|
||||
assertThat(env1).isNotSameAs(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 L3WithOverriddenConfigTests {
|
||||
|
||||
@Autowired
|
||||
Environment env3;
|
||||
|
||||
|
||||
@Test
|
||||
void propertiesInEnvironment() {
|
||||
assertThat(env1.getProperty("p1")).isEqualTo("v1");
|
||||
assertThat(env1).isNotSameAs(env2);
|
||||
assertThat(env2.getProperty("p1")).isEqualTo("v1");
|
||||
assertThat(env2.getProperty("p2a")).isEqualTo("v2a");
|
||||
assertThat(env2.getProperty("p2b")).isEqualTo("v2b");
|
||||
assertThat(env2).isNotSameAs(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 L4WithInheritedConfigButOverriddenTestPropertiesTests {
|
||||
|
||||
@Autowired
|
||||
Environment env4;
|
||||
|
||||
|
||||
@Test
|
||||
void propertiesInEnvironment() {
|
||||
assertThat(env1.getProperty("p1")).isEqualTo("v1");
|
||||
assertThat(env1).isNotSameAs(env2);
|
||||
assertThat(env2.getProperty("p1")).isEqualTo("v1");
|
||||
assertThat(env2.getProperty("p2a")).isEqualTo("v2a");
|
||||
assertThat(env2.getProperty("p2b")).isEqualTo("v2b");
|
||||
assertThat(env2).isNotSameAs(env3);
|
||||
assertThat(env3.getProperty("p1")).isNull();
|
||||
assertThat(env3.getProperty("p2")).isNull();
|
||||
assertThat(env3.getProperty("p3")).isEqualTo("v3");
|
||||
assertThat(env3).isNotSameAs(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 L5WithInheritedConfigAndTestInterfaceTests implements TestInterface {
|
||||
|
||||
@Autowired
|
||||
Environment env5;
|
||||
|
||||
|
||||
@Test
|
||||
void propertiesInEnvironment() {
|
||||
assertThat(env4).isNotSameAs(env5);
|
||||
assertThat(env5.getProperty("foo")).isEqualTo("bar");
|
||||
assertThat(env5.getProperty("enigma")).isEqualTo("42");
|
||||
assertThat(env5.getProperty("p1")).isNull();
|
||||
assertThat(env5.getProperty("p2")).isNull();
|
||||
assertThat(env5.getProperty("p3")).isEqualTo("v34");
|
||||
assertThat(env5.getProperty("p4")).isEqualTo("v4");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Configuration
|
||||
static class Config {
|
||||
/* no user beans required for these tests */
|
||||
}
|
||||
|
||||
@TestPropertySource(properties = { "foo = bar", "enigma: 42" })
|
||||
interface TestInterface {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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 javax.sql.DataSource;
|
||||
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
|
||||
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
|
||||
import org.springframework.test.annotation.Commit;
|
||||
import org.springframework.test.annotation.Rollback;
|
||||
import org.springframework.test.context.NestedTestConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
import org.springframework.test.context.transaction.TestTransaction;
|
||||
import org.springframework.transaction.TransactionManager;
|
||||
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
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;
|
||||
import static org.springframework.test.transaction.TransactionAssert.assertThatTransaction;
|
||||
import static org.springframework.transaction.annotation.Propagation.NOT_SUPPORTED;
|
||||
|
||||
/**
|
||||
* Integration tests that verify support for {@code @Nested} test classes using
|
||||
* {@link Transactional @Transactional} in conjunction with the
|
||||
* {@link SpringExtension} in a JUnit Jupiter environment.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 5.3
|
||||
*/
|
||||
@SpringJUnitConfig
|
||||
@Transactional
|
||||
@Commit
|
||||
class TransactionalNestedTests {
|
||||
|
||||
@Test
|
||||
void transactional(@Autowired DataSource dataSource) {
|
||||
assertThatTransaction().isActive();
|
||||
assertThat(dataSource).isNotNull();
|
||||
assertCommit();
|
||||
}
|
||||
|
||||
|
||||
@Nested
|
||||
@SpringJUnitConfig(Config.class)
|
||||
class ConfigOverriddenByDefaultTests {
|
||||
|
||||
@Test
|
||||
void notTransactional(@Autowired DataSource dataSource) {
|
||||
assertThatTransaction().isNotActive();
|
||||
assertThat(dataSource).isNotNull();
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
class InheritedConfigTests {
|
||||
|
||||
@Test
|
||||
void transactional(@Autowired DataSource dataSource) {
|
||||
assertThatTransaction().isActive();
|
||||
assertThat(dataSource).isNotNull();
|
||||
assertCommit();
|
||||
}
|
||||
|
||||
|
||||
@Nested
|
||||
class DoubleNestedWithImplicitlyInheritedConfigTests {
|
||||
|
||||
@Test
|
||||
void transactional(@Autowired DataSource dataSource) {
|
||||
assertThatTransaction().isActive();
|
||||
assertThat(dataSource).isNotNull();
|
||||
assertCommit();
|
||||
}
|
||||
|
||||
|
||||
@Nested
|
||||
@Rollback
|
||||
class TripleNestedWithImplicitlyInheritedConfigTests {
|
||||
|
||||
@Test
|
||||
void transactional(@Autowired DataSource dataSource) {
|
||||
assertThatTransaction().isActive();
|
||||
assertThat(dataSource).isNotNull();
|
||||
assertRollback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(OVERRIDE)
|
||||
@SpringJUnitConfig(Config.class)
|
||||
@Transactional
|
||||
@Rollback
|
||||
class DoubleNestedWithOverriddenConfigTests {
|
||||
|
||||
@Test
|
||||
void transactional(@Autowired DataSource dataSource) {
|
||||
assertThatTransaction().isActive();
|
||||
assertThat(dataSource).isNotNull();
|
||||
assertRollback();
|
||||
}
|
||||
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
@Commit
|
||||
class TripleNestedWithInheritedConfigTests {
|
||||
|
||||
@Test
|
||||
void transactional(@Autowired DataSource dataSource) {
|
||||
assertThatTransaction().isActive();
|
||||
assertThat(dataSource).isNotNull();
|
||||
assertCommit();
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
class TripleNestedWithInheritedConfigAndTestInterfaceTests implements TestInterface {
|
||||
|
||||
@Test
|
||||
void notTransactional(@Autowired DataSource dataSource) {
|
||||
assertThatTransaction().isNotActive();
|
||||
assertThat(dataSource).isNotNull();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void assertCommit() {
|
||||
assertThat(TestTransaction.isFlaggedForRollback()).as("flagged for commit").isFalse();
|
||||
}
|
||||
|
||||
private void assertRollback() {
|
||||
assertThat(TestTransaction.isFlaggedForRollback()).as("flagged for rollback").isTrue();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
static class Config {
|
||||
|
||||
@Bean
|
||||
TransactionManager transactionManager(DataSource dataSource) {
|
||||
return new DataSourceTransactionManager(dataSource);
|
||||
}
|
||||
|
||||
@Bean
|
||||
DataSource dataSource() {
|
||||
return new EmbeddedDatabaseBuilder().generateUniqueName(true).build();
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional(propagation = NOT_SUPPORTED)
|
||||
interface TestInterface {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* 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.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.NestedTestConfiguration;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
|
||||
import org.springframework.test.context.junit.jupiter.nested.WebAppConfigurationNestedTests.Config;
|
||||
import org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Integration tests that verify support for {@code @Nested} test classes using
|
||||
* {@link WebAppConfiguration @WebAppConfiguration} in conjunction with the
|
||||
* {@link SpringExtension} in a JUnit Jupiter environment.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 5.0
|
||||
* @see ConstructorInjectionNestedTests
|
||||
* @see org.springframework.test.context.junit4.nested.NestedTestsWithSpringRulesTests
|
||||
*/
|
||||
@SpringJUnitWebConfig(Config.class)
|
||||
class WebAppConfigurationNestedTests {
|
||||
|
||||
@Test
|
||||
void test(ApplicationContext context) {
|
||||
assertThat(context).isInstanceOf(WebApplicationContext.class);
|
||||
}
|
||||
|
||||
|
||||
@Nested
|
||||
@SpringJUnitConfig(Config.class)
|
||||
class ConfigOverriddenByDefaultTests {
|
||||
|
||||
@Test
|
||||
void test(ApplicationContext context) {
|
||||
assertThat(context).isNotInstanceOf(WebApplicationContext.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@SpringJUnitWebConfig(Config.class)
|
||||
class ConfigOverriddenByDefaultWebTests {
|
||||
|
||||
@Test
|
||||
void test(ApplicationContext context) {
|
||||
assertThat(context).isInstanceOf(WebApplicationContext.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
class NestedWithInheritedConfigTests {
|
||||
|
||||
@Test
|
||||
void test(ApplicationContext context) {
|
||||
assertThat(context).isInstanceOf(WebApplicationContext.class);
|
||||
}
|
||||
|
||||
|
||||
@Nested
|
||||
class DoubleNestedWithImplicitlyInheritedConfigWebTests {
|
||||
|
||||
@Test
|
||||
void test(ApplicationContext context) {
|
||||
assertThat(context).isInstanceOf(WebApplicationContext.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(OVERRIDE)
|
||||
@SpringJUnitConfig(Config.class)
|
||||
class DoubleNestedWithOverriddenConfigWebTests {
|
||||
|
||||
@Test
|
||||
void test(ApplicationContext context) {
|
||||
assertThat(context).isNotInstanceOf(WebApplicationContext.class);
|
||||
}
|
||||
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
class TripleNestedWithInheritedConfigWebTests {
|
||||
|
||||
@Test
|
||||
void test(ApplicationContext context) {
|
||||
assertThat(context).isNotInstanceOf(WebApplicationContext.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
class TripleNestedWithInheritedConfigAndTestInterfaceTests implements TestInterface {
|
||||
|
||||
@Test
|
||||
void test(ApplicationContext context) {
|
||||
assertThat(context).isInstanceOf(WebApplicationContext.class);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Configuration
|
||||
static class Config {
|
||||
}
|
||||
|
||||
@WebAppConfiguration
|
||||
interface TestInterface {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -33,12 +33,16 @@ import org.springframework.test.context.BootstrapTestUtils;
|
||||
import org.springframework.test.context.CacheAwareContextLoaderDelegate;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.ContextConfigurationAttributes;
|
||||
import org.springframework.test.context.ContextHierarchy;
|
||||
import org.springframework.test.context.ContextLoader;
|
||||
import org.springframework.test.context.MergedContextConfiguration;
|
||||
import org.springframework.test.context.NestedTestConfiguration;
|
||||
import org.springframework.test.context.TestContextBootstrapper;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.SoftAssertions.assertSoftly;
|
||||
import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.INHERIT;
|
||||
import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.OVERRIDE;
|
||||
|
||||
/**
|
||||
* Abstract base class for tests involving {@link ContextLoaderUtils},
|
||||
@@ -68,11 +72,13 @@ abstract class AbstractContextConfigurationUtilsTests {
|
||||
String[] expectedLocations, Class<?>[] expectedClasses,
|
||||
Class<? extends ContextLoader> expectedContextLoaderClass, boolean expectedInheritLocations) {
|
||||
|
||||
assertThat(attributes.getDeclaringClass()).as("declaring class").isEqualTo(expectedDeclaringClass);
|
||||
assertThat(attributes.getLocations()).as("locations").isEqualTo(expectedLocations);
|
||||
assertThat(attributes.getClasses()).as("classes").isEqualTo(expectedClasses);
|
||||
assertThat(attributes.isInheritLocations()).as("inherit locations").isEqualTo(expectedInheritLocations);
|
||||
assertThat(attributes.getContextLoaderClass()).as("context loader").isEqualTo(expectedContextLoaderClass);
|
||||
assertSoftly(softly -> {
|
||||
softly.assertThat(attributes.getDeclaringClass()).as("declaring class").isEqualTo(expectedDeclaringClass);
|
||||
softly.assertThat(attributes.getLocations()).as("locations").isEqualTo(expectedLocations);
|
||||
softly.assertThat(attributes.getClasses()).as("classes").isEqualTo(expectedClasses);
|
||||
softly.assertThat(attributes.isInheritLocations()).as("inherit locations").isEqualTo(expectedInheritLocations);
|
||||
softly.assertThat(attributes.getContextLoaderClass()).as("context loader").isEqualTo(expectedContextLoaderClass);
|
||||
});
|
||||
}
|
||||
|
||||
void assertMergedConfig(MergedContextConfiguration mergedConfig, Class<?> expectedTestClass,
|
||||
@@ -91,21 +97,22 @@ abstract class AbstractContextConfigurationUtilsTests {
|
||||
Set<Class<? extends ApplicationContextInitializer<?>>> expectedInitializerClasses,
|
||||
Class<? extends ContextLoader> expectedContextLoaderClass) {
|
||||
|
||||
assertThat(mergedConfig).isNotNull();
|
||||
assertThat(mergedConfig.getTestClass()).isEqualTo(expectedTestClass);
|
||||
assertThat(mergedConfig.getLocations()).isNotNull();
|
||||
assertThat(mergedConfig.getLocations()).isEqualTo(expectedLocations);
|
||||
assertThat(mergedConfig.getClasses()).isNotNull();
|
||||
assertThat(mergedConfig.getClasses()).isEqualTo(expectedClasses);
|
||||
assertThat(mergedConfig.getActiveProfiles()).isNotNull();
|
||||
if (expectedContextLoaderClass == null) {
|
||||
assertThat(mergedConfig.getContextLoader()).isNull();
|
||||
}
|
||||
else {
|
||||
assertThat(mergedConfig.getContextLoader().getClass()).isEqualTo(expectedContextLoaderClass);
|
||||
}
|
||||
assertThat(mergedConfig.getContextInitializerClasses()).isNotNull();
|
||||
assertThat(mergedConfig.getContextInitializerClasses()).isEqualTo(expectedInitializerClasses);
|
||||
assertSoftly(softly -> {
|
||||
softly.assertThat(mergedConfig).as("merged config").isNotNull();
|
||||
softly.assertThat(mergedConfig.getTestClass()).as("test class").isEqualTo(expectedTestClass);
|
||||
softly.assertThat(mergedConfig.getLocations()).as("locations").containsExactly(expectedLocations);
|
||||
softly.assertThat(mergedConfig.getClasses()).as("classes").containsExactly(expectedClasses);
|
||||
softly.assertThat(mergedConfig.getActiveProfiles()).as("active profiles").isNotNull();
|
||||
|
||||
if (expectedContextLoaderClass == null) {
|
||||
softly.assertThat(mergedConfig.getContextLoader()).as("context loader").isNull();
|
||||
}
|
||||
else {
|
||||
softly.assertThat(mergedConfig.getContextLoader().getClass()).as("context loader").isEqualTo(expectedContextLoaderClass);
|
||||
}
|
||||
softly.assertThat(mergedConfig.getContextInitializerClasses()).as("context initializers").isNotNull();
|
||||
softly.assertThat(mergedConfig.getContextInitializerClasses()).as("context initializers").isEqualTo(expectedInitializerClasses);
|
||||
});
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
@@ -130,6 +137,14 @@ abstract class AbstractContextConfigurationUtilsTests {
|
||||
static class BarConfig {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class BazConfig {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class QuuxConfig {
|
||||
}
|
||||
|
||||
@ContextConfiguration("/foo.xml")
|
||||
@ActiveProfiles(profiles = "foo")
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@@ -219,4 +234,46 @@ abstract class AbstractContextConfigurationUtilsTests {
|
||||
static class PropertiesClassesFoo {
|
||||
}
|
||||
|
||||
@ContextConfiguration(classes = FooConfig.class, loader = AnnotationConfigContextLoader.class)
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
static class OuterTestCase {
|
||||
|
||||
class NestedTestCaseWithInheritedConfig {
|
||||
}
|
||||
|
||||
@ContextConfiguration(classes = BarConfig.class)
|
||||
class NestedTestCaseWithMergedInheritedConfig {
|
||||
}
|
||||
|
||||
@NestedTestConfiguration(OVERRIDE)
|
||||
@ContextConfiguration(classes = BarConfig.class)
|
||||
class NestedTestCaseWithOverriddenConfig {
|
||||
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
class DoubleNestedTestCaseWithInheritedOverriddenConfig {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ContextHierarchy({ //
|
||||
@ContextConfiguration(classes = FooConfig.class, loader = AnnotationConfigContextLoader.class, name = "foo"), //
|
||||
@ContextConfiguration(classes = BarConfig.class, loader = AnnotationConfigContextLoader.class, name = "bar")//
|
||||
})
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
static class ContextHierarchyOuterTestCase {
|
||||
|
||||
class NestedTestCaseWithInheritedConfig {
|
||||
}
|
||||
|
||||
@ContextConfiguration(classes = BazConfig.class, loader = AnnotationConfigContextLoader.class, name = "bar")
|
||||
class NestedTestCaseWithMergedInheritedConfig {
|
||||
}
|
||||
|
||||
@ContextConfiguration(classes = QuuxConfig.class, loader = AnnotationConfigContextLoader.class, name = "foo", inheritLocations = false)
|
||||
class NestedTestCaseWithOverriddenConfig {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.assertj.core.api.AssertionsForClassTypes;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.test.context.BootstrapTestUtils;
|
||||
@@ -220,6 +221,137 @@ class BootstrapTestUtilsMergedConfigTests extends AbstractContextConfigurationUt
|
||||
assertThat(mergedConfig.getPropertySourceProperties()).isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 5.3
|
||||
*/
|
||||
@Test
|
||||
public void buildMergedConfigForNestedTestClassWithInheritedConfig() {
|
||||
Class<?> testClass = OuterTestCase.NestedTestCaseWithInheritedConfig.class;
|
||||
Class<?>[] expectedClasses = array(FooConfig.class);
|
||||
MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass);
|
||||
|
||||
assertMergedConfig(mergedConfig, testClass, EMPTY_STRING_ARRAY, expectedClasses,
|
||||
AnnotationConfigContextLoader.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 5.3
|
||||
*/
|
||||
@Test
|
||||
public void buildMergedConfigForNestedTestClassWithMergedInheritedConfig() {
|
||||
Class<?> testClass = OuterTestCase.NestedTestCaseWithMergedInheritedConfig.class;
|
||||
Class<?>[] expectedClasses = array(FooConfig.class, BarConfig.class);
|
||||
MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass);
|
||||
|
||||
assertMergedConfig(mergedConfig, testClass, EMPTY_STRING_ARRAY, expectedClasses,
|
||||
AnnotationConfigContextLoader.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 5.3
|
||||
*/
|
||||
@Test
|
||||
public void buildMergedConfigForNestedTestClassWithOverriddenConfig() {
|
||||
Class<?> testClass = OuterTestCase.NestedTestCaseWithOverriddenConfig.class;
|
||||
Class<?>[] expectedClasses = array(BarConfig.class);
|
||||
MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass);
|
||||
|
||||
assertMergedConfig(mergedConfig, testClass, EMPTY_STRING_ARRAY, expectedClasses,
|
||||
DelegatingSmartContextLoader.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 5.3
|
||||
*/
|
||||
@Test
|
||||
public void buildMergedConfigForDoubleNestedTestClassWithInheritedOverriddenConfig() {
|
||||
Class<?> testClass = OuterTestCase.NestedTestCaseWithOverriddenConfig.DoubleNestedTestCaseWithInheritedOverriddenConfig.class;
|
||||
Class<?>[] expectedClasses = array(BarConfig.class);
|
||||
MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass);
|
||||
|
||||
assertMergedConfig(mergedConfig, testClass, EMPTY_STRING_ARRAY, expectedClasses,
|
||||
DelegatingSmartContextLoader.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 5.3
|
||||
*/
|
||||
@Test
|
||||
public void buildMergedConfigForContextHierarchy() {
|
||||
Class<?> testClass = ContextHierarchyOuterTestCase.class;
|
||||
Class<?>[] expectedClasses = array(BarConfig.class);
|
||||
|
||||
MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass);
|
||||
assertThat(mergedConfig).as("merged config").isNotNull();
|
||||
|
||||
MergedContextConfiguration parent = mergedConfig.getParent();
|
||||
assertThat(parent).as("parent config").isNotNull();
|
||||
// The following does not work -- at least not in Eclipse.
|
||||
// asssertThat(parent.getClasses())...
|
||||
// So we use AssertionsForClassTypes directly.
|
||||
AssertionsForClassTypes.assertThat(parent.getClasses()).containsExactly(FooConfig.class);
|
||||
|
||||
assertMergedConfig(mergedConfig, testClass, EMPTY_STRING_ARRAY, expectedClasses,
|
||||
AnnotationConfigContextLoader.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 5.3
|
||||
*/
|
||||
@Test
|
||||
public void buildMergedConfigForNestedTestClassWithInheritedConfigForContextHierarchy() {
|
||||
Class<?> enclosingTestClass = ContextHierarchyOuterTestCase.class;
|
||||
Class<?> testClass = ContextHierarchyOuterTestCase.NestedTestCaseWithInheritedConfig.class;
|
||||
Class<?>[] expectedClasses = array(BarConfig.class);
|
||||
|
||||
MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass);
|
||||
assertThat(mergedConfig).as("merged config").isNotNull();
|
||||
|
||||
MergedContextConfiguration parent = mergedConfig.getParent();
|
||||
assertThat(parent).as("parent config").isNotNull();
|
||||
AssertionsForClassTypes.assertThat(parent.getClasses()).containsExactly(FooConfig.class);
|
||||
|
||||
assertMergedConfig(mergedConfig, enclosingTestClass, EMPTY_STRING_ARRAY, expectedClasses,
|
||||
AnnotationConfigContextLoader.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 5.3
|
||||
*/
|
||||
@Test
|
||||
public void buildMergedConfigForNestedTestClassWithMergedInheritedConfigForContextHierarchy() {
|
||||
Class<?> testClass = ContextHierarchyOuterTestCase.NestedTestCaseWithMergedInheritedConfig.class;
|
||||
Class<?>[] expectedClasses = array(BarConfig.class, BazConfig.class);
|
||||
|
||||
MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass);
|
||||
assertThat(mergedConfig).as("merged config").isNotNull();
|
||||
|
||||
MergedContextConfiguration parent = mergedConfig.getParent();
|
||||
assertThat(parent).as("parent config").isNotNull();
|
||||
AssertionsForClassTypes.assertThat(parent.getClasses()).containsExactly(FooConfig.class);
|
||||
|
||||
assertMergedConfig(mergedConfig, testClass, EMPTY_STRING_ARRAY, expectedClasses,
|
||||
AnnotationConfigContextLoader.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 5.3
|
||||
*/
|
||||
@Test
|
||||
public void buildMergedConfigForNestedTestClassWithOverriddenConfigForContextHierarchy() {
|
||||
Class<?> testClass = ContextHierarchyOuterTestCase.NestedTestCaseWithOverriddenConfig.class;
|
||||
MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass);
|
||||
assertThat(mergedConfig).as("merged config").isNotNull();
|
||||
|
||||
MergedContextConfiguration parent = mergedConfig.getParent();
|
||||
assertThat(parent).as("parent config").isNotNull();
|
||||
|
||||
assertMergedConfig(parent, testClass, EMPTY_STRING_ARRAY, array(QuuxConfig.class),
|
||||
AnnotationConfigContextLoader.class);
|
||||
assertMergedConfig(mergedConfig, ContextHierarchyOuterTestCase.class, EMPTY_STRING_ARRAY,
|
||||
array(BarConfig.class), AnnotationConfigContextLoader.class);
|
||||
}
|
||||
|
||||
|
||||
@ContextConfiguration
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
||||
@@ -19,12 +19,15 @@ package org.springframework.test.context.support;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.BDDMockito;
|
||||
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.annotation.DirtiesContext.ClassMode;
|
||||
import org.springframework.test.annotation.DirtiesContext.HierarchyMode;
|
||||
import org.springframework.test.context.NestedTestConfiguration;
|
||||
import org.springframework.test.context.TestContext;
|
||||
import org.springframework.test.context.TestExecutionListener;
|
||||
|
||||
@@ -40,6 +43,8 @@ import static org.springframework.test.annotation.DirtiesContext.ClassMode.BEFOR
|
||||
import static org.springframework.test.annotation.DirtiesContext.HierarchyMode.CURRENT_LEVEL;
|
||||
import static org.springframework.test.annotation.DirtiesContext.HierarchyMode.EXHAUSTIVE;
|
||||
import static org.springframework.test.annotation.DirtiesContext.MethodMode.BEFORE_METHOD;
|
||||
import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.INHERIT;
|
||||
import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.OVERRIDE;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link DirtiesContextBeforeModesTestExecutionListener}.
|
||||
@@ -48,6 +53,7 @@ import static org.springframework.test.annotation.DirtiesContext.MethodMode.BEFO
|
||||
* @author Sam Brannen
|
||||
* @since 4.0
|
||||
*/
|
||||
@DisplayName("@DirtiesContext TestExecutionListener tests")
|
||||
class DirtiesContextTestExecutionListenerTests {
|
||||
|
||||
private final TestExecutionListener beforeListener = new DirtiesContextBeforeModesTestExecutionListener();
|
||||
@@ -55,12 +61,261 @@ class DirtiesContextTestExecutionListenerTests {
|
||||
private final TestContext testContext = mock(TestContext.class);
|
||||
|
||||
|
||||
@Test
|
||||
void beforeAndAfterTestMethodForDirtiesContextDeclaredLocallyOnMethodWithBeforeMethodMode() throws Exception {
|
||||
Class<?> clazz = getClass();
|
||||
@Nested
|
||||
@DisplayName("Before and after test method")
|
||||
class BeforeAndAfterTestMethodTests {
|
||||
|
||||
@Test
|
||||
void declaredLocallyOnMethodWithBeforeMethodMode() throws Exception {
|
||||
Class<?> clazz = getClass().getEnclosingClass();
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
given(testContext.getTestMethod()).willReturn(
|
||||
clazz.getDeclaredMethod("dirtiesContextDeclaredLocallyWithBeforeMethodMode"));
|
||||
beforeListener.beforeTestMethod(testContext);
|
||||
afterListener.beforeTestMethod(testContext);
|
||||
verify(testContext, times(1)).markApplicationContextDirty(EXHAUSTIVE);
|
||||
afterListener.afterTestMethod(testContext);
|
||||
beforeListener.afterTestMethod(testContext);
|
||||
verify(testContext, times(1)).markApplicationContextDirty(EXHAUSTIVE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void declaredLocallyOnMethodWithAfterMethodMode() throws Exception {
|
||||
Class<?> clazz = getClass().getEnclosingClass();
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
given(testContext.getTestMethod()).willReturn(
|
||||
clazz.getDeclaredMethod("dirtiesContextDeclaredLocallyWithAfterMethodMode"));
|
||||
beforeListener.beforeTestMethod(testContext);
|
||||
afterListener.beforeTestMethod(testContext);
|
||||
verify(testContext, times(0)).markApplicationContextDirty(any(HierarchyMode.class));
|
||||
afterListener.afterTestMethod(testContext);
|
||||
beforeListener.afterTestMethod(testContext);
|
||||
verify(testContext, times(1)).markApplicationContextDirty(EXHAUSTIVE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void declaredOnMethodViaMetaAnnotationWithAfterMethodMode() throws Exception {
|
||||
Class<?> clazz = getClass().getEnclosingClass();
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
given(testContext.getTestMethod()).willReturn(
|
||||
clazz.getDeclaredMethod("dirtiesContextDeclaredViaMetaAnnotationWithAfterMethodMode"));
|
||||
beforeListener.beforeTestMethod(testContext);
|
||||
afterListener.beforeTestMethod(testContext);
|
||||
verify(testContext, times(0)).markApplicationContextDirty(any(HierarchyMode.class));
|
||||
afterListener.afterTestMethod(testContext);
|
||||
beforeListener.afterTestMethod(testContext);
|
||||
verify(testContext, times(1)).markApplicationContextDirty(EXHAUSTIVE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void declaredLocallyOnClassBeforeEachTestMethod() throws Exception {
|
||||
assertBeforeMethod(DirtiesContextDeclaredLocallyBeforeEachTestMethod.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void declaredLocallyOnClassAfterEachTestMethod() throws Exception {
|
||||
assertAfterMethod(DirtiesContextDeclaredLocallyAfterEachTestMethod.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void declaredViaMetaAnnotationOnClassAfterEachTestMethod() throws Exception {
|
||||
assertAfterMethod(DirtiesContextDeclaredViaMetaAnnotationAfterEachTestMethod.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void declaredLocallyOnClassBeforeClass() throws Exception {
|
||||
Class<?> clazz = DirtiesContextDeclaredLocallyBeforeClass.class;
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
given(testContext.getTestMethod()).willReturn(clazz.getDeclaredMethod("test"));
|
||||
beforeListener.beforeTestMethod(testContext);
|
||||
afterListener.beforeTestMethod(testContext);
|
||||
afterListener.afterTestMethod(testContext);
|
||||
beforeListener.afterTestMethod(testContext);
|
||||
verify(testContext, times(0)).markApplicationContextDirty(any(HierarchyMode.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void declaredLocallyOnClassAfterClass() throws Exception {
|
||||
Class<?> clazz = DirtiesContextDeclaredLocallyAfterClass.class;
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
given(testContext.getTestMethod()).willReturn(clazz.getDeclaredMethod("test"));
|
||||
beforeListener.beforeTestMethod(testContext);
|
||||
afterListener.beforeTestMethod(testContext);
|
||||
afterListener.afterTestMethod(testContext);
|
||||
beforeListener.afterTestMethod(testContext);
|
||||
verify(testContext, times(0)).markApplicationContextDirty(any(HierarchyMode.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void declaredViaMetaAnnotationOnClassAfterClass() throws Exception {
|
||||
Class<?> clazz = DirtiesContextDeclaredViaMetaAnnotationAfterClass.class;
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
given(testContext.getTestMethod()).willReturn(clazz.getDeclaredMethod("test"));
|
||||
beforeListener.beforeTestMethod(testContext);
|
||||
afterListener.beforeTestMethod(testContext);
|
||||
afterListener.afterTestMethod(testContext);
|
||||
beforeListener.afterTestMethod(testContext);
|
||||
verify(testContext, times(0)).markApplicationContextDirty(any(HierarchyMode.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void beforeAndAfterTestMethodForDirtiesContextViaMetaAnnotationWithOverrides() throws Exception {
|
||||
Class<?> clazz = DirtiesContextViaMetaAnnotationWithOverrides.class;
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
given(testContext.getTestMethod()).willReturn(clazz.getDeclaredMethod("test"));
|
||||
beforeListener.beforeTestMethod(testContext);
|
||||
afterListener.beforeTestMethod(testContext);
|
||||
verify(testContext, times(0)).markApplicationContextDirty(any(HierarchyMode.class));
|
||||
afterListener.afterTestMethod(testContext);
|
||||
beforeListener.afterTestMethod(testContext);
|
||||
verify(testContext, times(1)).markApplicationContextDirty(CURRENT_LEVEL);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Before and after test class")
|
||||
class BeforeAndAfterTestClassTests {
|
||||
|
||||
@Test
|
||||
void declaredLocallyOnMethod() throws Exception {
|
||||
Class<?> clazz = getClass().getEnclosingClass();
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
beforeListener.beforeTestClass(testContext);
|
||||
afterListener.beforeTestClass(testContext);
|
||||
afterListener.afterTestClass(testContext);
|
||||
beforeListener.afterTestClass(testContext);
|
||||
verify(testContext, times(0)).markApplicationContextDirty(any(HierarchyMode.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void declaredLocallyOnClassBeforeEachTestMethod() throws Exception {
|
||||
Class<?> clazz = DirtiesContextDeclaredLocallyBeforeEachTestMethod.class;
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
beforeListener.beforeTestClass(testContext);
|
||||
afterListener.beforeTestClass(testContext);
|
||||
afterListener.afterTestClass(testContext);
|
||||
beforeListener.afterTestClass(testContext);
|
||||
verify(testContext, times(0)).markApplicationContextDirty(any(HierarchyMode.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void declaredLocallyOnClassAfterEachTestMethod() throws Exception {
|
||||
Class<?> clazz = DirtiesContextDeclaredLocallyAfterEachTestMethod.class;
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
beforeListener.beforeTestClass(testContext);
|
||||
afterListener.beforeTestClass(testContext);
|
||||
afterListener.afterTestClass(testContext);
|
||||
beforeListener.afterTestClass(testContext);
|
||||
verify(testContext, times(0)).markApplicationContextDirty(any(HierarchyMode.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void declaredViaMetaAnnotationOnClassAfterEachTestMethod() throws Exception {
|
||||
Class<?> clazz = DirtiesContextDeclaredViaMetaAnnotationAfterEachTestMethod.class;
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
beforeListener.beforeTestClass(testContext);
|
||||
afterListener.beforeTestClass(testContext);
|
||||
afterListener.afterTestClass(testContext);
|
||||
beforeListener.afterTestClass(testContext);
|
||||
verify(testContext, times(0)).markApplicationContextDirty(any(HierarchyMode.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void declaredLocallyOnClassBeforeClass() throws Exception {
|
||||
assertBeforeClass(DirtiesContextDeclaredLocallyBeforeClass.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void declaredLocallyOnClassAfterClass() throws Exception {
|
||||
assertAfterClass(DirtiesContextDeclaredLocallyAfterClass.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void declaredViaMetaAnnotationOnClassAfterClass() throws Exception {
|
||||
assertAfterClass(DirtiesContextDeclaredViaMetaAnnotationAfterClass.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void declaredViaMetaAnnotationWithOverrides() throws Exception {
|
||||
Class<?> clazz = DirtiesContextViaMetaAnnotationWithOverrides.class;
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
beforeListener.beforeTestClass(testContext);
|
||||
afterListener.beforeTestClass(testContext);
|
||||
afterListener.afterTestClass(testContext);
|
||||
beforeListener.afterTestClass(testContext);
|
||||
verify(testContext, times(0)).markApplicationContextDirty(any(HierarchyMode.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void declaredViaMetaAnnotationWithOverriddenAttributes() throws Exception {
|
||||
assertAfterClass(DirtiesContextViaMetaAnnotationWithOverridenAttributes.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Nested config - before and after test method modes")
|
||||
class NestedBeforeAndAfterTestMethodTests {
|
||||
|
||||
@Test
|
||||
void onTopLevelClassWithBeforeEachTestMethod() throws Exception {
|
||||
assertBeforeMethod(BeforeAndAfterTestMethodTopLevelClass.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void onNestedClassWithConfigOverriddenByDefaultWithAfterClass() throws Exception {
|
||||
assertAfterMethod(BeforeAndAfterTestMethodTopLevelClass.ConfigOverriddenByDefault.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void onNestedClassWithInheritedConfigWithBeforeEachTestMethod() throws Exception {
|
||||
assertBeforeMethod(BeforeAndAfterTestMethodTopLevelClass.InheritedConfig.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void onNestedClassWithOverriddenConfigWithAfterClass() throws Exception {
|
||||
assertAfterMethod(BeforeAndAfterTestMethodTopLevelClass.OverriddenConfig.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void onNestedClassWithInheritedConfigButOverriddenWithBeforeEachTestMethod() throws Exception {
|
||||
assertBeforeMethod(BeforeAndAfterTestMethodTopLevelClass.OverriddenConfig.InheritedConfigButOverridden.class);
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@DisplayName("Nested config - before and after test class modes")
|
||||
class NestedBeforeAndAfterTestClassTests {
|
||||
|
||||
@Test
|
||||
void onTopLevelClassWithBeforeClass() throws Exception {
|
||||
assertBeforeClass(BeforeAndAfterTestClassTopLevelClass.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void onNestedClassWithConfigOverriddenByDefaultWithAfterClass() throws Exception {
|
||||
assertAfterClass(BeforeAndAfterTestClassTopLevelClass.ConfigOverriddenByDefault.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void onNestedClassWithInheritedConfigWithBeforeClass() throws Exception {
|
||||
assertBeforeClass(BeforeAndAfterTestClassTopLevelClass.InheritedConfig.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void onNestedClassWithOverriddenConfigWithAfterClass() throws Exception {
|
||||
assertAfterClass(BeforeAndAfterTestClassTopLevelClass.OverriddenConfig.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void onNestedClassWithInheritedConfigButOverriddenWithBeforeClass() throws Exception {
|
||||
assertBeforeClass(BeforeAndAfterTestClassTopLevelClass.OverriddenConfig.InheritedConfigButOverridden.class);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void assertBeforeMethod(Class<?> clazz) throws Exception {
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
given(testContext.getTestMethod()).willReturn(
|
||||
clazz.getDeclaredMethod("dirtiesContextDeclaredLocallyWithBeforeMethodMode"));
|
||||
given(testContext.getTestMethod()).willReturn(clazz.getDeclaredMethod("test"));
|
||||
beforeListener.beforeTestMethod(testContext);
|
||||
afterListener.beforeTestMethod(testContext);
|
||||
verify(testContext, times(1)).markApplicationContextDirty(EXHAUSTIVE);
|
||||
@@ -69,12 +324,9 @@ class DirtiesContextTestExecutionListenerTests {
|
||||
verify(testContext, times(1)).markApplicationContextDirty(EXHAUSTIVE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void beforeAndAfterTestMethodForDirtiesContextDeclaredLocallyOnMethodWithAfterMethodMode() throws Exception {
|
||||
Class<?> clazz = getClass();
|
||||
private void assertAfterMethod(Class<?> clazz) throws NoSuchMethodException, Exception {
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
given(testContext.getTestMethod()).willReturn(
|
||||
clazz.getDeclaredMethod("dirtiesContextDeclaredLocallyWithAfterMethodMode"));
|
||||
given(testContext.getTestMethod()).willReturn(clazz.getDeclaredMethod("test"));
|
||||
beforeListener.beforeTestMethod(testContext);
|
||||
afterListener.beforeTestMethod(testContext);
|
||||
verify(testContext, times(0)).markApplicationContextDirty(any(HierarchyMode.class));
|
||||
@@ -83,160 +335,7 @@ class DirtiesContextTestExecutionListenerTests {
|
||||
verify(testContext, times(1)).markApplicationContextDirty(EXHAUSTIVE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void beforeAndAfterTestMethodForDirtiesContextDeclaredOnMethodViaMetaAnnotationWithAfterMethodMode()
|
||||
throws Exception {
|
||||
Class<?> clazz = getClass();
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
given(testContext.getTestMethod()).willReturn(
|
||||
clazz.getDeclaredMethod("dirtiesContextDeclaredViaMetaAnnotationWithAfterMethodMode"));
|
||||
beforeListener.beforeTestMethod(testContext);
|
||||
afterListener.beforeTestMethod(testContext);
|
||||
verify(testContext, times(0)).markApplicationContextDirty(any(HierarchyMode.class));
|
||||
afterListener.afterTestMethod(testContext);
|
||||
beforeListener.afterTestMethod(testContext);
|
||||
verify(testContext, times(1)).markApplicationContextDirty(EXHAUSTIVE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void beforeAndAfterTestMethodForDirtiesContextDeclaredLocallyOnClassBeforeEachTestMethod() throws Exception {
|
||||
Class<?> clazz = DirtiesContextDeclaredLocallyBeforeEachTestMethod.class;
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
given(testContext.getTestMethod()).willReturn(clazz.getDeclaredMethod("clean"));
|
||||
beforeListener.beforeTestMethod(testContext);
|
||||
afterListener.beforeTestMethod(testContext);
|
||||
verify(testContext, times(1)).markApplicationContextDirty(EXHAUSTIVE);
|
||||
afterListener.afterTestMethod(testContext);
|
||||
beforeListener.afterTestMethod(testContext);
|
||||
verify(testContext, times(1)).markApplicationContextDirty(EXHAUSTIVE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void beforeAndAfterTestMethodForDirtiesContextDeclaredLocallyOnClassAfterEachTestMethod() throws Exception {
|
||||
Class<?> clazz = DirtiesContextDeclaredLocallyAfterEachTestMethod.class;
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
given(testContext.getTestMethod()).willReturn(clazz.getDeclaredMethod("clean"));
|
||||
beforeListener.beforeTestMethod(testContext);
|
||||
afterListener.beforeTestMethod(testContext);
|
||||
verify(testContext, times(0)).markApplicationContextDirty(any(HierarchyMode.class));
|
||||
afterListener.afterTestMethod(testContext);
|
||||
beforeListener.afterTestMethod(testContext);
|
||||
verify(testContext, times(1)).markApplicationContextDirty(EXHAUSTIVE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void beforeAndAfterTestMethodForDirtiesContextDeclaredViaMetaAnnotationOnClassAfterEachTestMethod()
|
||||
throws Exception {
|
||||
Class<?> clazz = DirtiesContextDeclaredViaMetaAnnotationAfterEachTestMethod.class;
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
given(testContext.getTestMethod()).willReturn(clazz.getDeclaredMethod("clean"));
|
||||
beforeListener.beforeTestMethod(testContext);
|
||||
afterListener.beforeTestMethod(testContext);
|
||||
verify(testContext, times(0)).markApplicationContextDirty(any(HierarchyMode.class));
|
||||
afterListener.afterTestMethod(testContext);
|
||||
beforeListener.afterTestMethod(testContext);
|
||||
verify(testContext, times(1)).markApplicationContextDirty(EXHAUSTIVE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void beforeAndAfterTestMethodForDirtiesContextDeclaredLocallyOnClassBeforeClass() throws Exception {
|
||||
Class<?> clazz = DirtiesContextDeclaredLocallyBeforeClass.class;
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
given(testContext.getTestMethod()).willReturn(clazz.getDeclaredMethod("clean"));
|
||||
beforeListener.beforeTestMethod(testContext);
|
||||
afterListener.beforeTestMethod(testContext);
|
||||
afterListener.afterTestMethod(testContext);
|
||||
beforeListener.afterTestMethod(testContext);
|
||||
verify(testContext, times(0)).markApplicationContextDirty(any(HierarchyMode.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void beforeAndAfterTestMethodForDirtiesContextDeclaredLocallyOnClassAfterClass() throws Exception {
|
||||
Class<?> clazz = DirtiesContextDeclaredLocallyAfterClass.class;
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
given(testContext.getTestMethod()).willReturn(clazz.getDeclaredMethod("clean"));
|
||||
beforeListener.beforeTestMethod(testContext);
|
||||
afterListener.beforeTestMethod(testContext);
|
||||
afterListener.afterTestMethod(testContext);
|
||||
beforeListener.afterTestMethod(testContext);
|
||||
verify(testContext, times(0)).markApplicationContextDirty(any(HierarchyMode.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void beforeAndAfterTestMethodForDirtiesContextDeclaredViaMetaAnnotationOnClassAfterClass() throws Exception {
|
||||
Class<?> clazz = DirtiesContextDeclaredViaMetaAnnotationAfterClass.class;
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
given(testContext.getTestMethod()).willReturn(clazz.getDeclaredMethod("clean"));
|
||||
beforeListener.beforeTestMethod(testContext);
|
||||
afterListener.beforeTestMethod(testContext);
|
||||
afterListener.afterTestMethod(testContext);
|
||||
beforeListener.afterTestMethod(testContext);
|
||||
verify(testContext, times(0)).markApplicationContextDirty(any(HierarchyMode.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void beforeAndAfterTestMethodForDirtiesContextViaMetaAnnotationWithOverrides() throws Exception {
|
||||
Class<?> clazz = DirtiesContextViaMetaAnnotationWithOverrides.class;
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
given(testContext.getTestMethod()).willReturn(clazz.getDeclaredMethod("clean"));
|
||||
beforeListener.beforeTestMethod(testContext);
|
||||
afterListener.beforeTestMethod(testContext);
|
||||
verify(testContext, times(0)).markApplicationContextDirty(any(HierarchyMode.class));
|
||||
afterListener.afterTestMethod(testContext);
|
||||
beforeListener.afterTestMethod(testContext);
|
||||
verify(testContext, times(1)).markApplicationContextDirty(CURRENT_LEVEL);
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Test
|
||||
void beforeAndAfterTestClassForDirtiesContextDeclaredLocallyOnMethod() throws Exception {
|
||||
Class<?> clazz = getClass();
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
beforeListener.beforeTestClass(testContext);
|
||||
afterListener.beforeTestClass(testContext);
|
||||
afterListener.afterTestClass(testContext);
|
||||
beforeListener.afterTestClass(testContext);
|
||||
verify(testContext, times(0)).markApplicationContextDirty(any(HierarchyMode.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void beforeAndAfterTestClassForDirtiesContextDeclaredLocallyOnClassBeforeEachTestMethod() throws Exception {
|
||||
Class<?> clazz = DirtiesContextDeclaredLocallyBeforeEachTestMethod.class;
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
beforeListener.beforeTestClass(testContext);
|
||||
afterListener.beforeTestClass(testContext);
|
||||
afterListener.afterTestClass(testContext);
|
||||
beforeListener.afterTestClass(testContext);
|
||||
verify(testContext, times(0)).markApplicationContextDirty(any(HierarchyMode.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void beforeAndAfterTestClassForDirtiesContextDeclaredLocallyOnClassAfterEachTestMethod() throws Exception {
|
||||
Class<?> clazz = DirtiesContextDeclaredLocallyAfterEachTestMethod.class;
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
beforeListener.beforeTestClass(testContext);
|
||||
afterListener.beforeTestClass(testContext);
|
||||
afterListener.afterTestClass(testContext);
|
||||
beforeListener.afterTestClass(testContext);
|
||||
verify(testContext, times(0)).markApplicationContextDirty(any(HierarchyMode.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void beforeAndAfterTestClassForDirtiesContextDeclaredViaMetaAnnotationOnClassAfterEachTestMethod()
|
||||
throws Exception {
|
||||
Class<?> clazz = DirtiesContextDeclaredViaMetaAnnotationAfterEachTestMethod.class;
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
beforeListener.beforeTestClass(testContext);
|
||||
afterListener.beforeTestClass(testContext);
|
||||
afterListener.afterTestClass(testContext);
|
||||
beforeListener.afterTestClass(testContext);
|
||||
verify(testContext, times(0)).markApplicationContextDirty(any(HierarchyMode.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void beforeAndAfterTestClassForDirtiesContextDeclaredLocallyOnClassBeforeClass() throws Exception {
|
||||
Class<?> clazz = DirtiesContextDeclaredLocallyBeforeClass.class;
|
||||
private void assertBeforeClass(Class<?> clazz) throws Exception {
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
beforeListener.beforeTestClass(testContext);
|
||||
afterListener.beforeTestClass(testContext);
|
||||
@@ -246,45 +345,7 @@ class DirtiesContextTestExecutionListenerTests {
|
||||
verify(testContext, times(1)).markApplicationContextDirty(EXHAUSTIVE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void beforeAndAfterTestClassForDirtiesContextDeclaredLocallyOnClassAfterClass() throws Exception {
|
||||
Class<?> clazz = DirtiesContextDeclaredLocallyAfterClass.class;
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
beforeListener.beforeTestClass(testContext);
|
||||
afterListener.beforeTestClass(testContext);
|
||||
verify(testContext, times(0)).markApplicationContextDirty(any(HierarchyMode.class));
|
||||
afterListener.afterTestClass(testContext);
|
||||
beforeListener.afterTestClass(testContext);
|
||||
verify(testContext, times(1)).markApplicationContextDirty(EXHAUSTIVE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void beforeAndAfterTestClassForDirtiesContextDeclaredViaMetaAnnotationOnClassAfterClass() throws Exception {
|
||||
Class<?> clazz = DirtiesContextDeclaredViaMetaAnnotationAfterClass.class;
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
beforeListener.beforeTestClass(testContext);
|
||||
afterListener.beforeTestClass(testContext);
|
||||
verify(testContext, times(0)).markApplicationContextDirty(any(HierarchyMode.class));
|
||||
afterListener.afterTestClass(testContext);
|
||||
beforeListener.afterTestClass(testContext);
|
||||
verify(testContext, times(1)).markApplicationContextDirty(EXHAUSTIVE);
|
||||
}
|
||||
|
||||
@Test
|
||||
void beforeAndAfterTestClassForDirtiesContextDeclaredViaMetaAnnotationWithOverrides() throws Exception {
|
||||
Class<?> clazz = DirtiesContextViaMetaAnnotationWithOverrides.class;
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
beforeListener.beforeTestClass(testContext);
|
||||
afterListener.beforeTestClass(testContext);
|
||||
afterListener.afterTestClass(testContext);
|
||||
beforeListener.afterTestClass(testContext);
|
||||
verify(testContext, times(0)).markApplicationContextDirty(any(HierarchyMode.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void beforeAndAfterTestClassForDirtiesContextDeclaredViaMetaAnnotationWithOverriddenAttributes()
|
||||
throws Exception {
|
||||
Class<?> clazz = DirtiesContextViaMetaAnnotationWithOverridenAttributes.class;
|
||||
private void assertAfterClass(Class<?> clazz) throws Exception {
|
||||
BDDMockito.<Class<?>> given(testContext.getTestClass()).willReturn(clazz);
|
||||
beforeListener.beforeTestClass(testContext);
|
||||
afterListener.beforeTestClass(testContext);
|
||||
@@ -298,54 +359,49 @@ class DirtiesContextTestExecutionListenerTests {
|
||||
|
||||
@DirtiesContext(methodMode = BEFORE_METHOD)
|
||||
void dirtiesContextDeclaredLocallyWithBeforeMethodMode() {
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
@DirtiesContext
|
||||
void dirtiesContextDeclaredLocallyWithAfterMethodMode() {
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
@MetaDirtyAfterMethod
|
||||
void dirtiesContextDeclaredViaMetaAnnotationWithAfterMethodMode() {
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
|
||||
@DirtiesContext
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
static @interface MetaDirtyAfterMethod {
|
||||
@interface MetaDirtyAfterMethod {
|
||||
}
|
||||
|
||||
@DirtiesContext(classMode = AFTER_EACH_TEST_METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
static @interface MetaDirtyAfterEachTestMethod {
|
||||
@interface MetaDirtyAfterEachTestMethod {
|
||||
}
|
||||
|
||||
@DirtiesContext(classMode = AFTER_CLASS)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
static @interface MetaDirtyAfterClass {
|
||||
@interface MetaDirtyAfterClass {
|
||||
}
|
||||
|
||||
@DirtiesContext(classMode = BEFORE_EACH_TEST_METHOD)
|
||||
static class DirtiesContextDeclaredLocallyBeforeEachTestMethod {
|
||||
|
||||
void clean() {
|
||||
/* no-op */
|
||||
void test() {
|
||||
}
|
||||
}
|
||||
|
||||
@DirtiesContext(classMode = AFTER_EACH_TEST_METHOD)
|
||||
static class DirtiesContextDeclaredLocallyAfterEachTestMethod {
|
||||
|
||||
void clean() {
|
||||
/* no-op */
|
||||
void test() {
|
||||
}
|
||||
}
|
||||
|
||||
@DirtiesContext
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
static @interface MetaDirtyWithOverrides {
|
||||
@interface MetaDirtyWithOverrides {
|
||||
|
||||
ClassMode classMode() default AFTER_EACH_TEST_METHOD;
|
||||
|
||||
@@ -355,48 +411,116 @@ class DirtiesContextTestExecutionListenerTests {
|
||||
@MetaDirtyAfterEachTestMethod
|
||||
static class DirtiesContextDeclaredViaMetaAnnotationAfterEachTestMethod {
|
||||
|
||||
void clean() {
|
||||
/* no-op */
|
||||
void test() {
|
||||
}
|
||||
}
|
||||
|
||||
@DirtiesContext(classMode = BEFORE_CLASS)
|
||||
static class DirtiesContextDeclaredLocallyBeforeClass {
|
||||
|
||||
void clean() {
|
||||
/* no-op */
|
||||
void test() {
|
||||
}
|
||||
}
|
||||
|
||||
@DirtiesContext(classMode = AFTER_CLASS)
|
||||
static class DirtiesContextDeclaredLocallyAfterClass {
|
||||
|
||||
void clean() {
|
||||
/* no-op */
|
||||
void test() {
|
||||
}
|
||||
}
|
||||
|
||||
@MetaDirtyAfterClass
|
||||
static class DirtiesContextDeclaredViaMetaAnnotationAfterClass {
|
||||
|
||||
void clean() {
|
||||
/* no-op */
|
||||
void test() {
|
||||
}
|
||||
}
|
||||
|
||||
@MetaDirtyWithOverrides
|
||||
static class DirtiesContextViaMetaAnnotationWithOverrides {
|
||||
|
||||
void clean() {
|
||||
/* no-op */
|
||||
void test() {
|
||||
}
|
||||
}
|
||||
|
||||
@MetaDirtyWithOverrides(classMode = AFTER_CLASS, hierarchyMode = EXHAUSTIVE)
|
||||
static class DirtiesContextViaMetaAnnotationWithOverridenAttributes {
|
||||
|
||||
void clean() {
|
||||
/* no-op */
|
||||
void test() {
|
||||
}
|
||||
}
|
||||
|
||||
@DirtiesContext(classMode = BEFORE_CLASS)
|
||||
static class BeforeAndAfterTestClassTopLevelClass {
|
||||
|
||||
void test() {
|
||||
}
|
||||
|
||||
|
||||
@DirtiesContext(classMode = AFTER_CLASS)
|
||||
class ConfigOverriddenByDefault {
|
||||
|
||||
void test() {
|
||||
}
|
||||
}
|
||||
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
class InheritedConfig {
|
||||
|
||||
void test() {
|
||||
}
|
||||
}
|
||||
|
||||
@NestedTestConfiguration(OVERRIDE)
|
||||
@DirtiesContext(classMode = AFTER_CLASS)
|
||||
class OverriddenConfig {
|
||||
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
@DirtiesContext(classMode = BEFORE_CLASS)
|
||||
class InheritedConfigButOverridden {
|
||||
|
||||
void test() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@DirtiesContext(classMode = BEFORE_EACH_TEST_METHOD)
|
||||
static class BeforeAndAfterTestMethodTopLevelClass {
|
||||
|
||||
void test() {
|
||||
}
|
||||
|
||||
|
||||
@DirtiesContext(classMode = AFTER_EACH_TEST_METHOD)
|
||||
class ConfigOverriddenByDefault {
|
||||
|
||||
void test() {
|
||||
}
|
||||
}
|
||||
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
class InheritedConfig {
|
||||
|
||||
void test() {
|
||||
}
|
||||
}
|
||||
|
||||
@NestedTestConfiguration(OVERRIDE)
|
||||
@DirtiesContext(classMode = AFTER_EACH_TEST_METHOD)
|
||||
class OverriddenConfig {
|
||||
|
||||
void test() {
|
||||
}
|
||||
|
||||
|
||||
@NestedTestConfiguration(INHERIT)
|
||||
@DirtiesContext(classMode = BEFORE_EACH_TEST_METHOD)
|
||||
class InheritedConfigButOverridden {
|
||||
|
||||
void test() {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
@@ -80,6 +81,7 @@ class TestPropertySourceUtilsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled("Validation for repeated @TestPropertySource annotations has been removed")
|
||||
void repeatedTestPropertySourcesWithConflictingInheritLocationsFlags() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> buildMergedTestPropertySources(RepeatedPropertySourcesWithConflictingInheritLocationsFlags.class))
|
||||
@@ -89,6 +91,7 @@ class TestPropertySourceUtilsTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Disabled("Validation for repeated @TestPropertySource annotations has been removed")
|
||||
void repeatedTestPropertySourcesWithConflictingInheritPropertiesFlags() {
|
||||
assertThatIllegalArgumentException()
|
||||
.isThrownBy(() -> buildMergedTestPropertySources(RepeatedPropertySourcesWithConflictingInheritPropertiesFlags.class))
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2020 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,12 +17,13 @@
|
||||
package org.springframework.test.util;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.junit.jupiter.api.DisplayName;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
@@ -47,489 +48,489 @@ import static org.springframework.test.util.MetaAnnotationUtils.findAnnotationDe
|
||||
*/
|
||||
class MetaAnnotationUtilsTests {
|
||||
|
||||
private void assertAtComponentOnComposedAnnotation(
|
||||
Class<?> rootDeclaringClass, String name, Class<? extends Annotation> composedAnnotationType) {
|
||||
@Nested
|
||||
@DisplayName("findAnnotationDescriptor() tests")
|
||||
class FindAnnotationDescriptorTests {
|
||||
|
||||
assertAtComponentOnComposedAnnotation(rootDeclaringClass, rootDeclaringClass, name, composedAnnotationType);
|
||||
}
|
||||
@Test
|
||||
void findAnnotationDescriptorWithNoAnnotationPresent() {
|
||||
assertThat(findAnnotationDescriptor(NonAnnotatedInterface.class, Transactional.class)).isNull();
|
||||
assertThat(findAnnotationDescriptor(NonAnnotatedClass.class, Transactional.class)).isNull();
|
||||
}
|
||||
|
||||
private void assertAtComponentOnComposedAnnotation(
|
||||
Class<?> startClass, Class<?> rootDeclaringClass, String name, Class<? extends Annotation> composedAnnotationType) {
|
||||
@Test
|
||||
void findAnnotationDescriptorWithInheritedAnnotationOnClass() {
|
||||
// Note: @Transactional is inherited
|
||||
assertThat(findAnnotationDescriptor(InheritedAnnotationClass.class, Transactional.class).getRootDeclaringClass()).isEqualTo(InheritedAnnotationClass.class);
|
||||
assertThat(findAnnotationDescriptor(SubInheritedAnnotationClass.class, Transactional.class).getRootDeclaringClass()).isEqualTo(InheritedAnnotationClass.class);
|
||||
}
|
||||
|
||||
assertAtComponentOnComposedAnnotation(startClass, rootDeclaringClass, composedAnnotationType, name, composedAnnotationType);
|
||||
}
|
||||
@Test
|
||||
void findAnnotationDescriptorWithInheritedAnnotationOnInterface() {
|
||||
// Note: @Transactional is inherited
|
||||
Transactional rawAnnotation = InheritedAnnotationInterface.class.getAnnotation(Transactional.class);
|
||||
AnnotationDescriptor<Transactional> descriptor =
|
||||
findAnnotationDescriptor(InheritedAnnotationInterface.class, Transactional.class);
|
||||
assertThat(descriptor).isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(InheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getDeclaringClass()).isEqualTo(InheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getAnnotation()).isEqualTo(rawAnnotation);
|
||||
|
||||
private void assertAtComponentOnComposedAnnotation(Class<?> startClass, Class<?> rootDeclaringClass,
|
||||
Class<?> declaringClass, String name, Class<? extends Annotation> composedAnnotationType) {
|
||||
descriptor = findAnnotationDescriptor(SubInheritedAnnotationInterface.class, Transactional.class);
|
||||
assertThat(descriptor).isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(SubInheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getDeclaringClass()).isEqualTo(InheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getAnnotation()).isEqualTo(rawAnnotation);
|
||||
|
||||
AnnotationDescriptor<Component> descriptor = findAnnotationDescriptor(startClass, Component.class);
|
||||
assertThat(descriptor).as("AnnotationDescriptor should not be null").isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).as("rootDeclaringClass").isEqualTo(rootDeclaringClass);
|
||||
assertThat(descriptor.getDeclaringClass()).as("declaringClass").isEqualTo(declaringClass);
|
||||
assertThat(descriptor.getAnnotationType()).as("annotationType").isEqualTo(Component.class);
|
||||
assertThat(descriptor.getAnnotation().value()).as("component name").isEqualTo(name);
|
||||
assertThat(descriptor.getComposedAnnotation()).as("composedAnnotation should not be null").isNotNull();
|
||||
assertThat(descriptor.getComposedAnnotationType()).as("composedAnnotationType").isEqualTo(composedAnnotationType);
|
||||
}
|
||||
descriptor = findAnnotationDescriptor(SubSubInheritedAnnotationInterface.class, Transactional.class);
|
||||
assertThat(descriptor).isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(SubSubInheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getDeclaringClass()).isEqualTo(InheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getAnnotation()).isEqualTo(rawAnnotation);
|
||||
}
|
||||
|
||||
private void assertAtComponentOnComposedAnnotationForMultipleCandidateTypes(
|
||||
Class<?> startClass, String name, Class<? extends Annotation> composedAnnotationType) {
|
||||
@Test
|
||||
void findAnnotationDescriptorForNonInheritedAnnotationOnClass() {
|
||||
// Note: @Order is not inherited.
|
||||
assertThat(findAnnotationDescriptor(NonInheritedAnnotationClass.class, Order.class).getRootDeclaringClass()).isEqualTo(NonInheritedAnnotationClass.class);
|
||||
assertThat(findAnnotationDescriptor(SubNonInheritedAnnotationClass.class, Order.class).getRootDeclaringClass()).isEqualTo(NonInheritedAnnotationClass.class);
|
||||
}
|
||||
|
||||
assertAtComponentOnComposedAnnotationForMultipleCandidateTypes(
|
||||
startClass, startClass, name, composedAnnotationType);
|
||||
}
|
||||
@Test
|
||||
void findAnnotationDescriptorForNonInheritedAnnotationOnInterface() {
|
||||
// Note: @Order is not inherited.
|
||||
Order rawAnnotation = NonInheritedAnnotationInterface.class.getAnnotation(Order.class);
|
||||
|
||||
private void assertAtComponentOnComposedAnnotationForMultipleCandidateTypes(Class<?> startClass,
|
||||
Class<?> rootDeclaringClass, String name, Class<? extends Annotation> composedAnnotationType) {
|
||||
AnnotationDescriptor<Order> descriptor =
|
||||
findAnnotationDescriptor(NonInheritedAnnotationInterface.class, Order.class);
|
||||
assertThat(descriptor).isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(NonInheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getDeclaringClass()).isEqualTo(NonInheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getAnnotation()).isEqualTo(rawAnnotation);
|
||||
|
||||
assertAtComponentOnComposedAnnotationForMultipleCandidateTypes(
|
||||
startClass, rootDeclaringClass, composedAnnotationType, name, composedAnnotationType);
|
||||
}
|
||||
descriptor = findAnnotationDescriptor(SubNonInheritedAnnotationInterface.class, Order.class);
|
||||
assertThat(descriptor).isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(SubNonInheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getDeclaringClass()).isEqualTo(NonInheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getAnnotation()).isEqualTo(rawAnnotation);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void assertAtComponentOnComposedAnnotationForMultipleCandidateTypes(Class<?> startClass,
|
||||
Class<?> rootDeclaringClass, Class<?> declaringClass, String name,
|
||||
Class<? extends Annotation> composedAnnotationType) {
|
||||
@Test
|
||||
void findAnnotationDescriptorWithMetaComponentAnnotation() {
|
||||
assertAtComponentOnComposedAnnotation(HasMetaComponentAnnotation.class, "meta1", Meta1.class);
|
||||
}
|
||||
|
||||
Class<Component> annotationType = Component.class;
|
||||
UntypedAnnotationDescriptor descriptor = findAnnotationDescriptorForTypes(
|
||||
startClass, Service.class, annotationType, Order.class, Transactional.class);
|
||||
|
||||
assertThat(descriptor).as("UntypedAnnotationDescriptor should not be null").isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).as("rootDeclaringClass").isEqualTo(rootDeclaringClass);
|
||||
assertThat(descriptor.getDeclaringClass()).as("declaringClass").isEqualTo(declaringClass);
|
||||
assertThat(descriptor.getAnnotationType()).as("annotationType").isEqualTo(annotationType);
|
||||
assertThat(((Component) descriptor.getAnnotation()).value()).as("component name").isEqualTo(name);
|
||||
assertThat(descriptor.getComposedAnnotation()).as("composedAnnotation should not be null").isNotNull();
|
||||
assertThat(descriptor.getComposedAnnotationType()).as("composedAnnotationType").isEqualTo(composedAnnotationType);
|
||||
}
|
||||
|
||||
@Test
|
||||
void findAnnotationDescriptorWithNoAnnotationPresent() {
|
||||
assertThat(findAnnotationDescriptor(NonAnnotatedInterface.class, Transactional.class)).isNull();
|
||||
assertThat(findAnnotationDescriptor(NonAnnotatedClass.class, Transactional.class)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void findAnnotationDescriptorWithInheritedAnnotationOnClass() {
|
||||
// Note: @Transactional is inherited
|
||||
assertThat(findAnnotationDescriptor(InheritedAnnotationClass.class, Transactional.class).getRootDeclaringClass()).isEqualTo(InheritedAnnotationClass.class);
|
||||
assertThat(findAnnotationDescriptor(SubInheritedAnnotationClass.class, Transactional.class).getRootDeclaringClass()).isEqualTo(InheritedAnnotationClass.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void findAnnotationDescriptorWithInheritedAnnotationOnInterface() {
|
||||
// Note: @Transactional is inherited
|
||||
Transactional rawAnnotation = InheritedAnnotationInterface.class.getAnnotation(Transactional.class);
|
||||
|
||||
AnnotationDescriptor<Transactional> descriptor =
|
||||
findAnnotationDescriptor(InheritedAnnotationInterface.class, Transactional.class);
|
||||
assertThat(descriptor).isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(InheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getDeclaringClass()).isEqualTo(InheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getAnnotation()).isEqualTo(rawAnnotation);
|
||||
|
||||
descriptor = findAnnotationDescriptor(SubInheritedAnnotationInterface.class, Transactional.class);
|
||||
assertThat(descriptor).isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(SubInheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getDeclaringClass()).isEqualTo(InheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getAnnotation()).isEqualTo(rawAnnotation);
|
||||
|
||||
descriptor = findAnnotationDescriptor(SubSubInheritedAnnotationInterface.class, Transactional.class);
|
||||
assertThat(descriptor).isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(SubSubInheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getDeclaringClass()).isEqualTo(InheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getAnnotation()).isEqualTo(rawAnnotation);
|
||||
}
|
||||
|
||||
@Test
|
||||
void findAnnotationDescriptorForNonInheritedAnnotationOnClass() {
|
||||
// Note: @Order is not inherited.
|
||||
assertThat(findAnnotationDescriptor(NonInheritedAnnotationClass.class, Order.class).getRootDeclaringClass()).isEqualTo(NonInheritedAnnotationClass.class);
|
||||
assertThat(findAnnotationDescriptor(SubNonInheritedAnnotationClass.class, Order.class).getRootDeclaringClass()).isEqualTo(NonInheritedAnnotationClass.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void findAnnotationDescriptorForNonInheritedAnnotationOnInterface() {
|
||||
// Note: @Order is not inherited.
|
||||
Order rawAnnotation = NonInheritedAnnotationInterface.class.getAnnotation(Order.class);
|
||||
|
||||
AnnotationDescriptor<Order> descriptor =
|
||||
findAnnotationDescriptor(NonInheritedAnnotationInterface.class, Order.class);
|
||||
assertThat(descriptor).isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(NonInheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getDeclaringClass()).isEqualTo(NonInheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getAnnotation()).isEqualTo(rawAnnotation);
|
||||
|
||||
descriptor = findAnnotationDescriptor(SubNonInheritedAnnotationInterface.class, Order.class);
|
||||
assertThat(descriptor).isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(SubNonInheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getDeclaringClass()).isEqualTo(NonInheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getAnnotation()).isEqualTo(rawAnnotation);
|
||||
}
|
||||
|
||||
@Test
|
||||
void findAnnotationDescriptorWithMetaComponentAnnotation() {
|
||||
assertAtComponentOnComposedAnnotation(HasMetaComponentAnnotation.class, "meta1", Meta1.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void findAnnotationDescriptorWithLocalAndMetaComponentAnnotation() {
|
||||
Class<Component> annotationType = Component.class;
|
||||
AnnotationDescriptor<Component> descriptor = findAnnotationDescriptor(
|
||||
@Test
|
||||
void findAnnotationDescriptorWithLocalAndMetaComponentAnnotation() {
|
||||
Class<Component> annotationType = Component.class;
|
||||
AnnotationDescriptor<Component> descriptor = findAnnotationDescriptor(
|
||||
HasLocalAndMetaComponentAnnotation.class, annotationType);
|
||||
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(HasLocalAndMetaComponentAnnotation.class);
|
||||
assertThat(descriptor.getAnnotationType()).isEqualTo(annotationType);
|
||||
assertThat(descriptor.getComposedAnnotation()).isNull();
|
||||
assertThat(descriptor.getComposedAnnotationType()).isNull();
|
||||
}
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(HasLocalAndMetaComponentAnnotation.class);
|
||||
assertThat(descriptor.getAnnotationType()).isEqualTo(annotationType);
|
||||
assertThat(descriptor.getComposedAnnotation()).isNull();
|
||||
assertThat(descriptor.getComposedAnnotationType()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void findAnnotationDescriptorForInterfaceWithMetaAnnotation() {
|
||||
assertAtComponentOnComposedAnnotation(InterfaceWithMetaAnnotation.class, "meta1", Meta1.class);
|
||||
}
|
||||
@Test
|
||||
void findAnnotationDescriptorForInterfaceWithMetaAnnotation() {
|
||||
assertAtComponentOnComposedAnnotation(InterfaceWithMetaAnnotation.class, "meta1", Meta1.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void findAnnotationDescriptorForClassWithMetaAnnotatedInterface() {
|
||||
Component rawAnnotation = AnnotationUtils.findAnnotation(ClassWithMetaAnnotatedInterface.class, Component.class);
|
||||
AnnotationDescriptor<Component> descriptor =
|
||||
findAnnotationDescriptor(ClassWithMetaAnnotatedInterface.class, Component.class);
|
||||
@Test
|
||||
void findAnnotationDescriptorForClassWithMetaAnnotatedInterface() {
|
||||
Component rawAnnotation = AnnotationUtils.findAnnotation(ClassWithMetaAnnotatedInterface.class, Component.class);
|
||||
AnnotationDescriptor<Component> descriptor =
|
||||
findAnnotationDescriptor(ClassWithMetaAnnotatedInterface.class, Component.class);
|
||||
|
||||
assertThat(descriptor).isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(ClassWithMetaAnnotatedInterface.class);
|
||||
assertThat(descriptor.getDeclaringClass()).isEqualTo(Meta1.class);
|
||||
assertThat(descriptor.getAnnotation()).isEqualTo(rawAnnotation);
|
||||
assertThat(descriptor.getComposedAnnotation().annotationType()).isEqualTo(Meta1.class);
|
||||
}
|
||||
assertThat(descriptor).isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(ClassWithMetaAnnotatedInterface.class);
|
||||
assertThat(descriptor.getDeclaringClass()).isEqualTo(Meta1.class);
|
||||
assertThat(descriptor.getAnnotation()).isEqualTo(rawAnnotation);
|
||||
assertThat(descriptor.getComposedAnnotation().annotationType()).isEqualTo(Meta1.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void findAnnotationDescriptorForClassWithLocalMetaAnnotationAndAnnotatedSuperclass() {
|
||||
AnnotationDescriptor<ContextConfiguration> descriptor = findAnnotationDescriptor(
|
||||
@Test
|
||||
void findAnnotationDescriptorForClassWithLocalMetaAnnotationAndAnnotatedSuperclass() {
|
||||
AnnotationDescriptor<ContextConfiguration> descriptor = findAnnotationDescriptor(
|
||||
MetaAnnotatedAndSuperAnnotatedContextConfigClass.class, ContextConfiguration.class);
|
||||
|
||||
assertThat(descriptor).as("AnnotationDescriptor should not be null").isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).as("rootDeclaringClass").isEqualTo(MetaAnnotatedAndSuperAnnotatedContextConfigClass.class);
|
||||
assertThat(descriptor.getDeclaringClass()).as("declaringClass").isEqualTo(MetaConfig.class);
|
||||
assertThat(descriptor.getAnnotationType()).as("annotationType").isEqualTo(ContextConfiguration.class);
|
||||
assertThat(descriptor.getComposedAnnotation()).as("composedAnnotation should not be null").isNotNull();
|
||||
assertThat(descriptor.getComposedAnnotationType()).as("composedAnnotationType").isEqualTo(MetaConfig.class);
|
||||
assertThat(descriptor).as("AnnotationDescriptor should not be null").isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).as("rootDeclaringClass").isEqualTo(MetaAnnotatedAndSuperAnnotatedContextConfigClass.class);
|
||||
assertThat(descriptor.getDeclaringClass()).as("declaringClass").isEqualTo(MetaConfig.class);
|
||||
assertThat(descriptor.getAnnotationType()).as("annotationType").isEqualTo(ContextConfiguration.class);
|
||||
assertThat(descriptor.getComposedAnnotation()).as("composedAnnotation should not be null").isNotNull();
|
||||
assertThat(descriptor.getComposedAnnotationType()).as("composedAnnotationType").isEqualTo(MetaConfig.class);
|
||||
|
||||
assertThat(descriptor.getAnnotationAttributes().getClassArray("classes")).as("configured classes").isEqualTo(new Class<?>[] {String.class});
|
||||
}
|
||||
assertThat(descriptor.getAnnotationAttributes().getClassArray("classes")).as("configured classes").isEqualTo(new Class<?>[] {String.class});
|
||||
}
|
||||
|
||||
@Test
|
||||
void findAnnotationDescriptorForClassWithLocalMetaAnnotationAndMetaAnnotatedInterface() {
|
||||
assertAtComponentOnComposedAnnotation(ClassWithLocalMetaAnnotationAndMetaAnnotatedInterface.class, "meta2", Meta2.class);
|
||||
}
|
||||
@Test
|
||||
void findAnnotationDescriptorForClassWithLocalMetaAnnotationAndMetaAnnotatedInterface() {
|
||||
assertAtComponentOnComposedAnnotation(ClassWithLocalMetaAnnotationAndMetaAnnotatedInterface.class, "meta2", Meta2.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void findAnnotationDescriptorForSubClassWithLocalMetaAnnotationAndMetaAnnotatedInterface() {
|
||||
assertAtComponentOnComposedAnnotation(SubClassWithLocalMetaAnnotationAndMetaAnnotatedInterface.class,
|
||||
@Test
|
||||
void findAnnotationDescriptorForSubClassWithLocalMetaAnnotationAndMetaAnnotatedInterface() {
|
||||
assertAtComponentOnComposedAnnotation(SubClassWithLocalMetaAnnotationAndMetaAnnotatedInterface.class,
|
||||
ClassWithLocalMetaAnnotationAndMetaAnnotatedInterface.class, "meta2", Meta2.class);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.0.3
|
||||
*/
|
||||
@Test
|
||||
void findAnnotationDescriptorOnMetaMetaAnnotatedClass() {
|
||||
Class<MetaMetaAnnotatedClass> startClass = MetaMetaAnnotatedClass.class;
|
||||
assertAtComponentOnComposedAnnotation(startClass, startClass, Meta2.class, "meta2", MetaMeta.class);
|
||||
}
|
||||
/**
|
||||
* @since 4.0.3
|
||||
*/
|
||||
@Test
|
||||
void findAnnotationDescriptorOnMetaMetaAnnotatedClass() {
|
||||
Class<MetaMetaAnnotatedClass> startClass = MetaMetaAnnotatedClass.class;
|
||||
assertAtComponentOnComposedAnnotation(startClass, startClass, Meta2.class, "meta2", MetaMeta.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.0.3
|
||||
*/
|
||||
@Test
|
||||
void findAnnotationDescriptorOnMetaMetaMetaAnnotatedClass() {
|
||||
Class<MetaMetaMetaAnnotatedClass> startClass = MetaMetaMetaAnnotatedClass.class;
|
||||
assertAtComponentOnComposedAnnotation(startClass, startClass, Meta2.class, "meta2", MetaMetaMeta.class);
|
||||
}
|
||||
/**
|
||||
* @since 4.0.3
|
||||
*/
|
||||
@Test
|
||||
void findAnnotationDescriptorOnMetaMetaMetaAnnotatedClass() {
|
||||
Class<MetaMetaMetaAnnotatedClass> startClass = MetaMetaMetaAnnotatedClass.class;
|
||||
assertAtComponentOnComposedAnnotation(startClass, startClass, Meta2.class, "meta2", MetaMetaMeta.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.0.3
|
||||
*/
|
||||
@Test
|
||||
void findAnnotationDescriptorOnAnnotatedClassWithMissingTargetMetaAnnotation() {
|
||||
// InheritedAnnotationClass is NOT annotated or meta-annotated with @Component
|
||||
AnnotationDescriptor<Component> descriptor = findAnnotationDescriptor(
|
||||
/**
|
||||
* @since 4.0.3
|
||||
*/
|
||||
@Test
|
||||
void findAnnotationDescriptorOnAnnotatedClassWithMissingTargetMetaAnnotation() {
|
||||
// InheritedAnnotationClass is NOT annotated or meta-annotated with @Component
|
||||
AnnotationDescriptor<Component> descriptor = findAnnotationDescriptor(
|
||||
InheritedAnnotationClass.class, Component.class);
|
||||
assertThat(descriptor).as("Should not find @Component on InheritedAnnotationClass").isNull();
|
||||
}
|
||||
assertThat(descriptor).as("Should not find @Component on InheritedAnnotationClass").isNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.0.3
|
||||
*/
|
||||
@Test
|
||||
void findAnnotationDescriptorOnMetaCycleAnnotatedClassWithMissingTargetMetaAnnotation() {
|
||||
AnnotationDescriptor<Component> descriptor = findAnnotationDescriptor(
|
||||
/**
|
||||
* @since 4.0.3
|
||||
*/
|
||||
@Test
|
||||
void findAnnotationDescriptorOnMetaCycleAnnotatedClassWithMissingTargetMetaAnnotation() {
|
||||
AnnotationDescriptor<Component> descriptor = findAnnotationDescriptor(
|
||||
MetaCycleAnnotatedClass.class, Component.class);
|
||||
assertThat(descriptor).as("Should not find @Component on MetaCycleAnnotatedClass").isNull();
|
||||
assertThat(descriptor).as("Should not find @Component on MetaCycleAnnotatedClass").isNull();
|
||||
}
|
||||
|
||||
private void assertAtComponentOnComposedAnnotation(
|
||||
Class<?> rootDeclaringClass, String name, Class<? extends Annotation> composedAnnotationType) {
|
||||
|
||||
assertAtComponentOnComposedAnnotation(rootDeclaringClass, rootDeclaringClass, name, composedAnnotationType);
|
||||
}
|
||||
|
||||
private void assertAtComponentOnComposedAnnotation(
|
||||
Class<?> startClass, Class<?> rootDeclaringClass, String name, Class<? extends Annotation> composedAnnotationType) {
|
||||
|
||||
assertAtComponentOnComposedAnnotation(startClass, rootDeclaringClass, composedAnnotationType, name, composedAnnotationType);
|
||||
}
|
||||
|
||||
private void assertAtComponentOnComposedAnnotation(Class<?> startClass, Class<?> rootDeclaringClass,
|
||||
Class<?> declaringClass, String name, Class<? extends Annotation> composedAnnotationType) {
|
||||
|
||||
AnnotationDescriptor<Component> descriptor = findAnnotationDescriptor(startClass, Component.class);
|
||||
assertThat(descriptor).as("AnnotationDescriptor should not be null").isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).as("rootDeclaringClass").isEqualTo(rootDeclaringClass);
|
||||
assertThat(descriptor.getDeclaringClass()).as("declaringClass").isEqualTo(declaringClass);
|
||||
assertThat(descriptor.getAnnotationType()).as("annotationType").isEqualTo(Component.class);
|
||||
assertThat(descriptor.getAnnotation().value()).as("component name").isEqualTo(name);
|
||||
assertThat(descriptor.getComposedAnnotation()).as("composedAnnotation should not be null").isNotNull();
|
||||
assertThat(descriptor.getComposedAnnotationType()).as("composedAnnotationType").isEqualTo(composedAnnotationType);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@Nested
|
||||
@DisplayName("findAnnotationDescriptorForTypes() tests")
|
||||
class FindAnnotationDescriptorForTypesTests {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void findAnnotationDescriptorForTypesWithNoAnnotationPresent() {
|
||||
assertThat(findAnnotationDescriptorForTypes(NonAnnotatedInterface.class, Transactional.class, Component.class)).isNull();
|
||||
assertThat(findAnnotationDescriptorForTypes(NonAnnotatedClass.class, Transactional.class, Order.class)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void findAnnotationDescriptorForTypesWithInheritedAnnotationOnClass() {
|
||||
// Note: @Transactional is inherited
|
||||
assertThat(findAnnotationDescriptorForTypes(InheritedAnnotationClass.class, Transactional.class).getRootDeclaringClass()).isEqualTo(InheritedAnnotationClass.class);
|
||||
assertThat(findAnnotationDescriptorForTypes(SubInheritedAnnotationClass.class, Transactional.class).getRootDeclaringClass()).isEqualTo(InheritedAnnotationClass.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void findAnnotationDescriptorForTypesWithInheritedAnnotationOnInterface() {
|
||||
// Note: @Transactional is inherited
|
||||
Transactional rawAnnotation = InheritedAnnotationInterface.class.getAnnotation(Transactional.class);
|
||||
|
||||
UntypedAnnotationDescriptor descriptor =
|
||||
findAnnotationDescriptorForTypes(InheritedAnnotationInterface.class, Transactional.class);
|
||||
assertThat(descriptor).isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(InheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getDeclaringClass()).isEqualTo(InheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getAnnotation()).isEqualTo(rawAnnotation);
|
||||
|
||||
descriptor = findAnnotationDescriptorForTypes(SubInheritedAnnotationInterface.class, Transactional.class);
|
||||
assertThat(descriptor).isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(SubInheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getDeclaringClass()).isEqualTo(InheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getAnnotation()).isEqualTo(rawAnnotation);
|
||||
|
||||
descriptor = findAnnotationDescriptorForTypes(SubSubInheritedAnnotationInterface.class, Transactional.class);
|
||||
assertThat(descriptor).isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(SubSubInheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getDeclaringClass()).isEqualTo(InheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getAnnotation()).isEqualTo(rawAnnotation);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void findAnnotationDescriptorForTypesForNonInheritedAnnotationOnClass() {
|
||||
// Note: @Order is not inherited.
|
||||
assertThat(findAnnotationDescriptorForTypes(NonInheritedAnnotationClass.class, Order.class).getRootDeclaringClass()).isEqualTo(NonInheritedAnnotationClass.class);
|
||||
assertThat(findAnnotationDescriptorForTypes(SubNonInheritedAnnotationClass.class, Order.class).getRootDeclaringClass()).isEqualTo(NonInheritedAnnotationClass.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void findAnnotationDescriptorForTypesForNonInheritedAnnotationOnInterface() {
|
||||
// Note: @Order is not inherited.
|
||||
Order rawAnnotation = NonInheritedAnnotationInterface.class.getAnnotation(Order.class);
|
||||
|
||||
UntypedAnnotationDescriptor descriptor =
|
||||
findAnnotationDescriptorForTypes(NonInheritedAnnotationInterface.class, Order.class);
|
||||
assertThat(descriptor).isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(NonInheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getDeclaringClass()).isEqualTo(NonInheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getAnnotation()).isEqualTo(rawAnnotation);
|
||||
|
||||
descriptor = findAnnotationDescriptorForTypes(SubNonInheritedAnnotationInterface.class, Order.class);
|
||||
assertThat(descriptor).isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(SubNonInheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getDeclaringClass()).isEqualTo(NonInheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getAnnotation()).isEqualTo(rawAnnotation);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void findAnnotationDescriptorForTypesWithLocalAndMetaComponentAnnotation() {
|
||||
Class<Component> annotationType = Component.class;
|
||||
UntypedAnnotationDescriptor descriptor = findAnnotationDescriptorForTypes(
|
||||
HasLocalAndMetaComponentAnnotation.class, Transactional.class, annotationType, Order.class);
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(HasLocalAndMetaComponentAnnotation.class);
|
||||
assertThat(descriptor.getAnnotationType()).isEqualTo(annotationType);
|
||||
assertThat(descriptor.getComposedAnnotation()).isNull();
|
||||
assertThat(descriptor.getComposedAnnotationType()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void findAnnotationDescriptorForTypesWithMetaComponentAnnotation() {
|
||||
Class<HasMetaComponentAnnotation> startClass = HasMetaComponentAnnotation.class;
|
||||
assertAtComponentOnComposedAnnotationForMultipleCandidateTypes(startClass, "meta1", Meta1.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void findAnnotationDescriptorForTypesWithMetaAnnotationWithDefaultAttributes() {
|
||||
Class<?> startClass = MetaConfigWithDefaultAttributesTestCase.class;
|
||||
Class<ContextConfiguration> annotationType = ContextConfiguration.class;
|
||||
|
||||
UntypedAnnotationDescriptor descriptor = findAnnotationDescriptorForTypes(startClass,
|
||||
Service.class, ContextConfiguration.class, Order.class, Transactional.class);
|
||||
|
||||
assertThat(descriptor).isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(startClass);
|
||||
assertThat(descriptor.getAnnotationType()).isEqualTo(annotationType);
|
||||
assertThat(((ContextConfiguration) descriptor.getAnnotation()).value()).isEqualTo(new Class<?>[] {});
|
||||
assertThat(descriptor.getAnnotationAttributes().getClassArray("classes")).isEqualTo(new Class<?>[] {MetaConfig.DevConfig.class, MetaConfig.ProductionConfig.class});
|
||||
assertThat(descriptor.getComposedAnnotation()).isNotNull();
|
||||
assertThat(descriptor.getComposedAnnotationType()).isEqualTo(MetaConfig.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void findAnnotationDescriptorForTypesWithMetaAnnotationWithOverriddenAttributes() {
|
||||
Class<?> startClass = MetaConfigWithOverriddenAttributesTestCase.class;
|
||||
Class<ContextConfiguration> annotationType = ContextConfiguration.class;
|
||||
|
||||
UntypedAnnotationDescriptor descriptor = findAnnotationDescriptorForTypes(
|
||||
startClass, Service.class, ContextConfiguration.class, Order.class, Transactional.class);
|
||||
|
||||
assertThat(descriptor).isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(startClass);
|
||||
assertThat(descriptor.getAnnotationType()).isEqualTo(annotationType);
|
||||
assertThat(((ContextConfiguration) descriptor.getAnnotation()).value()).isEqualTo(new Class<?>[] {});
|
||||
assertThat(descriptor.getAnnotationAttributes().getClassArray("classes")).isEqualTo(new Class<?>[] {MetaAnnotationUtilsTests.class});
|
||||
assertThat(descriptor.getComposedAnnotation()).isNotNull();
|
||||
assertThat(descriptor.getComposedAnnotationType()).isEqualTo(MetaConfig.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void findAnnotationDescriptorForTypesForInterfaceWithMetaAnnotation() {
|
||||
Class<InterfaceWithMetaAnnotation> startClass = InterfaceWithMetaAnnotation.class;
|
||||
assertAtComponentOnComposedAnnotationForMultipleCandidateTypes(startClass, "meta1", Meta1.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void findAnnotationDescriptorForTypesForClassWithMetaAnnotatedInterface() {
|
||||
Component rawAnnotation = AnnotationUtils.findAnnotation(ClassWithMetaAnnotatedInterface.class, Component.class);
|
||||
|
||||
UntypedAnnotationDescriptor descriptor = findAnnotationDescriptorForTypes(
|
||||
ClassWithMetaAnnotatedInterface.class, Service.class, Component.class, Order.class, Transactional.class);
|
||||
|
||||
assertThat(descriptor).isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(ClassWithMetaAnnotatedInterface.class);
|
||||
assertThat(descriptor.getDeclaringClass()).isEqualTo(Meta1.class);
|
||||
assertThat(descriptor.getAnnotation()).isEqualTo(rawAnnotation);
|
||||
assertThat(descriptor.getComposedAnnotation().annotationType()).isEqualTo(Meta1.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void findAnnotationDescriptorForTypesForClassWithLocalMetaAnnotationAndMetaAnnotatedInterface() {
|
||||
Class<ClassWithLocalMetaAnnotationAndMetaAnnotatedInterface> startClass = ClassWithLocalMetaAnnotationAndMetaAnnotatedInterface.class;
|
||||
assertAtComponentOnComposedAnnotationForMultipleCandidateTypes(startClass, "meta2", Meta2.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void findAnnotationDescriptorForTypesForSubClassWithLocalMetaAnnotationAndMetaAnnotatedInterface() {
|
||||
assertAtComponentOnComposedAnnotationForMultipleCandidateTypes(
|
||||
SubClassWithLocalMetaAnnotationAndMetaAnnotatedInterface.class,
|
||||
ClassWithLocalMetaAnnotationAndMetaAnnotatedInterface.class, "meta2", Meta2.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.0.3
|
||||
*/
|
||||
@Test
|
||||
void findAnnotationDescriptorForTypesOnMetaMetaAnnotatedClass() {
|
||||
Class<MetaMetaAnnotatedClass> startClass = MetaMetaAnnotatedClass.class;
|
||||
assertAtComponentOnComposedAnnotationForMultipleCandidateTypes(
|
||||
startClass, startClass, Meta2.class, "meta2", MetaMeta.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.0.3
|
||||
*/
|
||||
@Test
|
||||
void findAnnotationDescriptorForTypesOnMetaMetaMetaAnnotatedClass() {
|
||||
Class<MetaMetaMetaAnnotatedClass> startClass = MetaMetaMetaAnnotatedClass.class;
|
||||
assertAtComponentOnComposedAnnotationForMultipleCandidateTypes(
|
||||
startClass, startClass, Meta2.class, "meta2", MetaMetaMeta.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.0.3
|
||||
*/
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void findAnnotationDescriptorForTypesOnAnnotatedClassWithMissingTargetMetaAnnotation() {
|
||||
// InheritedAnnotationClass is NOT annotated or meta-annotated with @Component,
|
||||
// @Service, or @Order, but it is annotated with @Transactional.
|
||||
UntypedAnnotationDescriptor descriptor = findAnnotationDescriptorForTypes(
|
||||
InheritedAnnotationClass.class, Service.class, Component.class, Order.class);
|
||||
assertThat(descriptor).as("Should not find @Component on InheritedAnnotationClass").isNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.0.3
|
||||
*/
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void findAnnotationDescriptorForTypesOnMetaCycleAnnotatedClassWithMissingTargetMetaAnnotation() {
|
||||
UntypedAnnotationDescriptor descriptor = findAnnotationDescriptorForTypes(
|
||||
MetaCycleAnnotatedClass.class, Service.class, Component.class, Order.class);
|
||||
assertThat(descriptor).as("Should not find @Component on MetaCycleAnnotatedClass").isNull();
|
||||
}
|
||||
|
||||
private void assertAtComponentOnComposedAnnotationForMultipleCandidateTypes(
|
||||
Class<?> startClass, String name, Class<? extends Annotation> composedAnnotationType) {
|
||||
|
||||
assertAtComponentOnComposedAnnotationForMultipleCandidateTypes(
|
||||
startClass, startClass, name, composedAnnotationType);
|
||||
}
|
||||
|
||||
private void assertAtComponentOnComposedAnnotationForMultipleCandidateTypes(Class<?> startClass,
|
||||
Class<?> rootDeclaringClass, String name, Class<? extends Annotation> composedAnnotationType) {
|
||||
|
||||
assertAtComponentOnComposedAnnotationForMultipleCandidateTypes(
|
||||
startClass, rootDeclaringClass, composedAnnotationType, name, composedAnnotationType);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void assertAtComponentOnComposedAnnotationForMultipleCandidateTypes(Class<?> startClass,
|
||||
Class<?> rootDeclaringClass, Class<?> declaringClass, String name,
|
||||
Class<? extends Annotation> composedAnnotationType) {
|
||||
|
||||
Class<Component> annotationType = Component.class;
|
||||
UntypedAnnotationDescriptor descriptor = findAnnotationDescriptorForTypes(
|
||||
startClass, Service.class, annotationType, Order.class, Transactional.class);
|
||||
|
||||
assertThat(descriptor).as("UntypedAnnotationDescriptor should not be null").isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).as("rootDeclaringClass").isEqualTo(rootDeclaringClass);
|
||||
assertThat(descriptor.getDeclaringClass()).as("declaringClass").isEqualTo(declaringClass);
|
||||
assertThat(descriptor.getAnnotationType()).as("annotationType").isEqualTo(annotationType);
|
||||
assertThat(((Component) descriptor.getAnnotation()).value()).as("component name").isEqualTo(name);
|
||||
assertThat(descriptor.getComposedAnnotation()).as("composedAnnotation should not be null").isNotNull();
|
||||
assertThat(descriptor.getComposedAnnotationType()).as("composedAnnotationType").isEqualTo(composedAnnotationType);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void findAnnotationDescriptorForTypesWithNoAnnotationPresent() {
|
||||
assertThat(findAnnotationDescriptorForTypes(NonAnnotatedInterface.class, Transactional.class, Component.class)).isNull();
|
||||
assertThat(findAnnotationDescriptorForTypes(NonAnnotatedClass.class, Transactional.class, Order.class)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void findAnnotationDescriptorForTypesWithInheritedAnnotationOnClass() {
|
||||
// Note: @Transactional is inherited
|
||||
assertThat(findAnnotationDescriptorForTypes(InheritedAnnotationClass.class, Transactional.class).getRootDeclaringClass()).isEqualTo(InheritedAnnotationClass.class);
|
||||
assertThat(findAnnotationDescriptorForTypes(SubInheritedAnnotationClass.class, Transactional.class).getRootDeclaringClass()).isEqualTo(InheritedAnnotationClass.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void findAnnotationDescriptorForTypesWithInheritedAnnotationOnInterface() {
|
||||
// Note: @Transactional is inherited
|
||||
Transactional rawAnnotation = InheritedAnnotationInterface.class.getAnnotation(Transactional.class);
|
||||
|
||||
UntypedAnnotationDescriptor descriptor =
|
||||
findAnnotationDescriptorForTypes(InheritedAnnotationInterface.class, Transactional.class);
|
||||
assertThat(descriptor).isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(InheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getDeclaringClass()).isEqualTo(InheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getAnnotation()).isEqualTo(rawAnnotation);
|
||||
|
||||
descriptor = findAnnotationDescriptorForTypes(SubInheritedAnnotationInterface.class, Transactional.class);
|
||||
assertThat(descriptor).isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(SubInheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getDeclaringClass()).isEqualTo(InheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getAnnotation()).isEqualTo(rawAnnotation);
|
||||
|
||||
descriptor = findAnnotationDescriptorForTypes(SubSubInheritedAnnotationInterface.class, Transactional.class);
|
||||
assertThat(descriptor).isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(SubSubInheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getDeclaringClass()).isEqualTo(InheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getAnnotation()).isEqualTo(rawAnnotation);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void findAnnotationDescriptorForTypesForNonInheritedAnnotationOnClass() {
|
||||
// Note: @Order is not inherited.
|
||||
assertThat(findAnnotationDescriptorForTypes(NonInheritedAnnotationClass.class, Order.class).getRootDeclaringClass()).isEqualTo(NonInheritedAnnotationClass.class);
|
||||
assertThat(findAnnotationDescriptorForTypes(SubNonInheritedAnnotationClass.class, Order.class).getRootDeclaringClass()).isEqualTo(NonInheritedAnnotationClass.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void findAnnotationDescriptorForTypesForNonInheritedAnnotationOnInterface() {
|
||||
// Note: @Order is not inherited.
|
||||
Order rawAnnotation = NonInheritedAnnotationInterface.class.getAnnotation(Order.class);
|
||||
|
||||
UntypedAnnotationDescriptor descriptor =
|
||||
findAnnotationDescriptorForTypes(NonInheritedAnnotationInterface.class, Order.class);
|
||||
assertThat(descriptor).isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(NonInheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getDeclaringClass()).isEqualTo(NonInheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getAnnotation()).isEqualTo(rawAnnotation);
|
||||
|
||||
descriptor = findAnnotationDescriptorForTypes(SubNonInheritedAnnotationInterface.class, Order.class);
|
||||
assertThat(descriptor).isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(SubNonInheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getDeclaringClass()).isEqualTo(NonInheritedAnnotationInterface.class);
|
||||
assertThat(descriptor.getAnnotation()).isEqualTo(rawAnnotation);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void findAnnotationDescriptorForTypesWithLocalAndMetaComponentAnnotation() {
|
||||
Class<Component> annotationType = Component.class;
|
||||
UntypedAnnotationDescriptor descriptor = findAnnotationDescriptorForTypes(
|
||||
HasLocalAndMetaComponentAnnotation.class, Transactional.class, annotationType, Order.class);
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(HasLocalAndMetaComponentAnnotation.class);
|
||||
assertThat(descriptor.getAnnotationType()).isEqualTo(annotationType);
|
||||
assertThat(descriptor.getComposedAnnotation()).isNull();
|
||||
assertThat(descriptor.getComposedAnnotationType()).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void findAnnotationDescriptorForTypesWithMetaComponentAnnotation() {
|
||||
Class<HasMetaComponentAnnotation> startClass = HasMetaComponentAnnotation.class;
|
||||
assertAtComponentOnComposedAnnotationForMultipleCandidateTypes(startClass, "meta1", Meta1.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void findAnnotationDescriptorForTypesWithMetaAnnotationWithDefaultAttributes() {
|
||||
Class<?> startClass = MetaConfigWithDefaultAttributesTestCase.class;
|
||||
Class<ContextConfiguration> annotationType = ContextConfiguration.class;
|
||||
|
||||
UntypedAnnotationDescriptor descriptor = findAnnotationDescriptorForTypes(startClass,
|
||||
Service.class, ContextConfiguration.class, Order.class, Transactional.class);
|
||||
|
||||
assertThat(descriptor).isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(startClass);
|
||||
assertThat(descriptor.getAnnotationType()).isEqualTo(annotationType);
|
||||
assertThat(((ContextConfiguration) descriptor.getAnnotation()).value()).isEqualTo(new Class<?>[] {});
|
||||
assertThat(descriptor.getAnnotationAttributes().getClassArray("classes")).isEqualTo(new Class<?>[] {MetaConfig.DevConfig.class, MetaConfig.ProductionConfig.class});
|
||||
assertThat(descriptor.getComposedAnnotation()).isNotNull();
|
||||
assertThat(descriptor.getComposedAnnotationType()).isEqualTo(MetaConfig.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void findAnnotationDescriptorForTypesWithMetaAnnotationWithOverriddenAttributes() {
|
||||
Class<?> startClass = MetaConfigWithOverriddenAttributesTestCase.class;
|
||||
Class<ContextConfiguration> annotationType = ContextConfiguration.class;
|
||||
|
||||
UntypedAnnotationDescriptor descriptor = findAnnotationDescriptorForTypes(
|
||||
startClass, Service.class, ContextConfiguration.class, Order.class, Transactional.class);
|
||||
|
||||
assertThat(descriptor).isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(startClass);
|
||||
assertThat(descriptor.getAnnotationType()).isEqualTo(annotationType);
|
||||
assertThat(((ContextConfiguration) descriptor.getAnnotation()).value()).isEqualTo(new Class<?>[] {});
|
||||
assertThat(descriptor.getAnnotationAttributes().getClassArray("classes")).isEqualTo(new Class<?>[] {MetaAnnotationUtilsTests.class});
|
||||
assertThat(descriptor.getComposedAnnotation()).isNotNull();
|
||||
assertThat(descriptor.getComposedAnnotationType()).isEqualTo(MetaConfig.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void findAnnotationDescriptorForTypesForInterfaceWithMetaAnnotation() {
|
||||
Class<InterfaceWithMetaAnnotation> startClass = InterfaceWithMetaAnnotation.class;
|
||||
assertAtComponentOnComposedAnnotationForMultipleCandidateTypes(startClass, "meta1", Meta1.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void findAnnotationDescriptorForTypesForClassWithMetaAnnotatedInterface() {
|
||||
Component rawAnnotation = AnnotationUtils.findAnnotation(ClassWithMetaAnnotatedInterface.class, Component.class);
|
||||
|
||||
UntypedAnnotationDescriptor descriptor = findAnnotationDescriptorForTypes(
|
||||
ClassWithMetaAnnotatedInterface.class, Service.class, Component.class, Order.class, Transactional.class);
|
||||
|
||||
assertThat(descriptor).isNotNull();
|
||||
assertThat(descriptor.getRootDeclaringClass()).isEqualTo(ClassWithMetaAnnotatedInterface.class);
|
||||
assertThat(descriptor.getDeclaringClass()).isEqualTo(Meta1.class);
|
||||
assertThat(descriptor.getAnnotation()).isEqualTo(rawAnnotation);
|
||||
assertThat(descriptor.getComposedAnnotation().annotationType()).isEqualTo(Meta1.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void findAnnotationDescriptorForTypesForClassWithLocalMetaAnnotationAndMetaAnnotatedInterface() {
|
||||
Class<ClassWithLocalMetaAnnotationAndMetaAnnotatedInterface> startClass = ClassWithLocalMetaAnnotationAndMetaAnnotatedInterface.class;
|
||||
assertAtComponentOnComposedAnnotationForMultipleCandidateTypes(startClass, "meta2", Meta2.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void findAnnotationDescriptorForTypesForSubClassWithLocalMetaAnnotationAndMetaAnnotatedInterface() {
|
||||
assertAtComponentOnComposedAnnotationForMultipleCandidateTypes(
|
||||
SubClassWithLocalMetaAnnotationAndMetaAnnotatedInterface.class,
|
||||
ClassWithLocalMetaAnnotationAndMetaAnnotatedInterface.class, "meta2", Meta2.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.0.3
|
||||
*/
|
||||
@Test
|
||||
void findAnnotationDescriptorForTypesOnMetaMetaAnnotatedClass() {
|
||||
Class<MetaMetaAnnotatedClass> startClass = MetaMetaAnnotatedClass.class;
|
||||
assertAtComponentOnComposedAnnotationForMultipleCandidateTypes(
|
||||
startClass, startClass, Meta2.class, "meta2", MetaMeta.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.0.3
|
||||
*/
|
||||
@Test
|
||||
void findAnnotationDescriptorForTypesOnMetaMetaMetaAnnotatedClass() {
|
||||
Class<MetaMetaMetaAnnotatedClass> startClass = MetaMetaMetaAnnotatedClass.class;
|
||||
assertAtComponentOnComposedAnnotationForMultipleCandidateTypes(
|
||||
startClass, startClass, Meta2.class, "meta2", MetaMetaMeta.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.0.3
|
||||
*/
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void findAnnotationDescriptorForTypesOnAnnotatedClassWithMissingTargetMetaAnnotation() {
|
||||
// InheritedAnnotationClass is NOT annotated or meta-annotated with @Component,
|
||||
// @Service, or @Order, but it is annotated with @Transactional.
|
||||
UntypedAnnotationDescriptor descriptor = findAnnotationDescriptorForTypes(
|
||||
InheritedAnnotationClass.class, Service.class, Component.class, Order.class);
|
||||
assertThat(descriptor).as("Should not find @Component on InheritedAnnotationClass").isNull();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.0.3
|
||||
*/
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void findAnnotationDescriptorForTypesOnMetaCycleAnnotatedClassWithMissingTargetMetaAnnotation() {
|
||||
UntypedAnnotationDescriptor descriptor = findAnnotationDescriptorForTypes(
|
||||
MetaCycleAnnotatedClass.class, Service.class, Component.class, Order.class);
|
||||
assertThat(descriptor).as("Should not find @Component on MetaCycleAnnotatedClass").isNull();
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Component(value = "meta1")
|
||||
@Order
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
@Documented
|
||||
static @interface Meta1 {
|
||||
@interface Meta1 {
|
||||
}
|
||||
|
||||
@Component(value = "meta2")
|
||||
@Transactional
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
@Documented
|
||||
static @interface Meta2 {
|
||||
@interface Meta2 {
|
||||
}
|
||||
|
||||
@Meta2
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
@Documented
|
||||
@interface MetaMeta {
|
||||
}
|
||||
|
||||
@MetaMeta
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
@Documented
|
||||
@interface MetaMetaMeta {
|
||||
}
|
||||
|
||||
@MetaCycle3
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.ANNOTATION_TYPE)
|
||||
@Documented
|
||||
@interface MetaCycle1 {
|
||||
}
|
||||
|
||||
@MetaCycle1
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.ANNOTATION_TYPE)
|
||||
@Documented
|
||||
@interface MetaCycle2 {
|
||||
}
|
||||
|
||||
@MetaCycle2
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
@Documented
|
||||
@interface MetaCycle3 {
|
||||
}
|
||||
|
||||
@ContextConfiguration
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
@Documented
|
||||
static @interface MetaConfig {
|
||||
@interface MetaConfig {
|
||||
|
||||
static class DevConfig {
|
||||
}
|
||||
@@ -554,7 +555,7 @@ class MetaAnnotationUtilsTests {
|
||||
}
|
||||
|
||||
@Meta1
|
||||
static interface InterfaceWithMetaAnnotation {
|
||||
interface InterfaceWithMetaAnnotation {
|
||||
}
|
||||
|
||||
static class ClassWithMetaAnnotatedInterface implements InterfaceWithMetaAnnotation {
|
||||
@@ -591,26 +592,26 @@ class MetaAnnotationUtilsTests {
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
@Transactional
|
||||
static interface InheritedAnnotationInterface {
|
||||
interface InheritedAnnotationInterface {
|
||||
}
|
||||
|
||||
static interface SubInheritedAnnotationInterface extends InheritedAnnotationInterface {
|
||||
interface SubInheritedAnnotationInterface extends InheritedAnnotationInterface {
|
||||
}
|
||||
|
||||
static interface SubSubInheritedAnnotationInterface extends SubInheritedAnnotationInterface {
|
||||
interface SubSubInheritedAnnotationInterface extends SubInheritedAnnotationInterface {
|
||||
}
|
||||
|
||||
@Order
|
||||
static interface NonInheritedAnnotationInterface {
|
||||
interface NonInheritedAnnotationInterface {
|
||||
}
|
||||
|
||||
static interface SubNonInheritedAnnotationInterface extends NonInheritedAnnotationInterface {
|
||||
interface SubNonInheritedAnnotationInterface extends NonInheritedAnnotationInterface {
|
||||
}
|
||||
|
||||
static class NonAnnotatedClass {
|
||||
}
|
||||
|
||||
static interface NonAnnotatedInterface {
|
||||
interface NonAnnotatedInterface {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
|
||||
Reference in New Issue
Block a user