diff --git a/spring-test/src/main/java/org/springframework/test/context/ContextLoaderUtils.java b/spring-test/src/main/java/org/springframework/test/context/ContextLoaderUtils.java index a43897eb0b6..f71e447b6c4 100644 --- a/spring-test/src/main/java/org/springframework/test/context/ContextLoaderUtils.java +++ b/spring-test/src/main/java/org/springframework/test/context/ContextLoaderUtils.java @@ -237,11 +237,9 @@ abstract class ContextLoaderUtils { * never {@code null} * @throws IllegalArgumentException if the supplied class is {@code null}; if * neither {@code @ContextConfiguration} nor {@code @ContextHierarchy} is - * present on the supplied class; if a given class in the class hierarchy + * present on the supplied class; or if a given class in the class hierarchy * declares both {@code @ContextConfiguration} and {@code @ContextHierarchy} as - * top-level annotations; or if individual {@code @ContextConfiguration} - * elements within a {@code @ContextHierarchy} declaration on a given class - * in the class hierarchy do not define unique context configuration. + * top-level annotations. * * @since 3.2.2 * @see #buildContextHierarchyMap(Class) @@ -287,17 +285,6 @@ abstract class ContextLoaderUtils { convertContextConfigToConfigAttributesAndAddToList(contextConfiguration, declaringClass, configAttributesList); } - - // Check for uniqueness - Set configAttributesSet = new HashSet( - configAttributesList); - if (configAttributesSet.size() != configAttributesList.size()) { - String msg = String.format("The @ContextConfiguration elements configured via " - + "@ContextHierarchy in test class [%s] must define unique contexts to load.", - declaringClass.getName()); - logger.error(msg); - throw new IllegalStateException(msg); - } } else { // This should theoretically actually never happen... @@ -336,6 +323,9 @@ abstract class ContextLoaderUtils { * (must not be {@code null}) * @return a map of context configuration attributes for the context hierarchy, * keyed by context hierarchy level name; never {@code null} + * @throws IllegalArgumentException if the lists of context configuration + * attributes for each level in the {@code @ContextHierarchy} do not define + * unique context configuration within the overall hierarchy. * * @since 3.2.2 * @see #resolveContextHierarchyAttributes(Class) @@ -363,6 +353,16 @@ abstract class ContextLoaderUtils { } } + // Check for uniqueness + Set> set = new HashSet>(map.values()); + if (set.size() != map.size()) { + String msg = String.format("The @ContextConfiguration elements configured via " + + "@ContextHierarchy in test class [%s] and its superclasses must " + + "define unique contexts per hierarchy level.", testClass.getName()); + logger.error(msg); + throw new IllegalStateException(msg); + } + return map; } diff --git a/spring-test/src/test/java/org/springframework/test/context/ContextLoaderUtilsTests.java b/spring-test/src/test/java/org/springframework/test/context/ContextLoaderUtilsTests.java index ecedda4ddf9..9553efc8343 100644 --- a/spring-test/src/test/java/org/springframework/test/context/ContextLoaderUtilsTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/ContextLoaderUtilsTests.java @@ -225,29 +225,6 @@ public class ContextLoaderUtilsTests { assertThat(configAttributesListClassLevel3.get(2).getLocations()[0], equalTo("3-C.xml")); } - private void assertContextConfigEntriesAreNotUnique(Class testClass) { - try { - resolveContextHierarchyAttributes(testClass); - fail("Should throw an IllegalStateException"); - } - catch (IllegalStateException e) { - String msg = String.format( - "The @ContextConfiguration elements configured via @ContextHierarchy in test class [%s] must define unique contexts to load.", - testClass.getName()); - assertEquals(msg, e.getMessage()); - } - } - - @Test - public void resolveContextHierarchyAttributesForSingleTestClassWithMultiLevelContextHierarchyWithEmptyContextConfig() { - assertContextConfigEntriesAreNotUnique(SingleTestClassWithMultiLevelContextHierarchyWithEmptyContextConfig.class); - } - - @Test - public void resolveContextHierarchyAttributesForSingleTestClassWithMultiLevelContextHierarchyWithDuplicatedContextConfig() { - assertContextConfigEntriesAreNotUnique(SingleTestClassWithMultiLevelContextHierarchyWithDuplicatedContextConfig.class); - } - @Test public void buildContextHierarchyMapForTestClassHierarchyWithMultiLevelContextHierarchies() { Map> map = buildContextHierarchyMap(TestClass3WithMultiLevelContextHierarchy.class); @@ -335,6 +312,58 @@ public class ContextLoaderUtilsTests { assertThat(level3Config.get(0).getLocations()[0], is("2-C.xml")); } + private void assertContextConfigEntriesAreNotUnique(Class testClass) { + try { + buildContextHierarchyMap(testClass); + fail("Should throw an IllegalStateException"); + } + catch (IllegalStateException e) { + String msg = String.format( + "The @ContextConfiguration elements configured via @ContextHierarchy in test class [%s] and its superclasses must define unique contexts per hierarchy level.", + testClass.getName()); + assertEquals(msg, e.getMessage()); + } + } + + @Test + public void buildContextHierarchyMapForSingleTestClassWithMultiLevelContextHierarchyWithEmptyContextConfig() { + assertContextConfigEntriesAreNotUnique(SingleTestClassWithMultiLevelContextHierarchyWithEmptyContextConfig.class); + } + + @Test + public void buildContextHierarchyMapForSingleTestClassWithMultiLevelContextHierarchyWithDuplicatedContextConfig() { + assertContextConfigEntriesAreNotUnique(SingleTestClassWithMultiLevelContextHierarchyWithDuplicatedContextConfig.class); + } + + /** + * Used to reproduce bug reported in https://jira.springsource.org/browse/SPR-10997 + */ + @Test + public void buildContextHierarchyMapForTestClassHierarchyWithMultiLevelContextHierarchiesAndOverriddenInitializers() { + Map> map = buildContextHierarchyMap(TestClass2WithMultiLevelContextHierarchyWithOverriddenInitializers.class); + + assertThat(map.size(), is(2)); + assertThat(map.keySet(), hasItems("alpha", "beta")); + + List alphaConfig = map.get("alpha"); + assertThat(alphaConfig.size(), is(2)); + assertThat(alphaConfig.get(0).getLocations().length, is(1)); + assertThat(alphaConfig.get(0).getLocations()[0], is("1-A.xml")); + assertThat(alphaConfig.get(0).getInitializers().length, is(0)); + assertThat(alphaConfig.get(1).getLocations().length, is(0)); + assertThat(alphaConfig.get(1).getInitializers().length, is(1)); + assertEquals(DummyApplicationContextInitializer.class, alphaConfig.get(1).getInitializers()[0]); + + List betaConfig = map.get("beta"); + assertThat(betaConfig.size(), is(2)); + assertThat(betaConfig.get(0).getLocations().length, is(1)); + assertThat(betaConfig.get(0).getLocations()[0], is("1-B.xml")); + assertThat(betaConfig.get(0).getInitializers().length, is(0)); + assertThat(betaConfig.get(1).getLocations().length, is(0)); + assertThat(betaConfig.get(1).getInitializers().length, is(1)); + assertEquals(DummyApplicationContextInitializer.class, betaConfig.get(1).getInitializers()[0]); + } + @Test(expected = IllegalStateException.class) public void resolveConfigAttributesWithConflictingLocations() { resolveContextConfigurationAttributes(ConflictingLocations.class); @@ -843,4 +872,40 @@ public class ContextLoaderUtilsTests { private static class SingleTestClassWithMultiLevelContextHierarchyWithDuplicatedContextConfig { } + /** + * Used to reproduce bug reported in https://jira.springsource.org/browse/SPR-10997 + */ + @ContextHierarchy({// + // + @ContextConfiguration(name = "alpha", locations = "1-A.xml"),// + @ContextConfiguration(name = "beta", locations = "1-B.xml") // + }) + private static class TestClass1WithMultiLevelContextHierarchyWithUniqueContextConfig { + } + + /** + * Used to reproduce bug reported in https://jira.springsource.org/browse/SPR-10997 + */ + @ContextHierarchy({// + // + @ContextConfiguration(name = "alpha", initializers = DummyApplicationContextInitializer.class),// + @ContextConfiguration(name = "beta", initializers = DummyApplicationContextInitializer.class) // + }) + private static class TestClass2WithMultiLevelContextHierarchyWithOverriddenInitializers extends + TestClass1WithMultiLevelContextHierarchyWithUniqueContextConfig { + } + + /** + * Used to reproduce bug reported in https://jira.springsource.org/browse/SPR-10997 + */ + private static class DummyApplicationContextInitializer implements + ApplicationContextInitializer { + + @Override + public void initialize(ConfigurableApplicationContext applicationContext) { + /* no-op */ + } + + } + }