From 7658d856cac027ae367f04833bee6c43c62b5534 Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Mon, 21 Oct 2013 19:33:04 +0200 Subject: [PATCH] Assert context uniqueness against merged config Prior to this commit, the uniqueness check for @ContextConfiguration attributes within a @ContextHierarchy was performed at a single test class level instead of against the merged configuration for all test class levels in the test class hierarchy. This commit addresses this issue by moving the uniqueness check algorithm from resolveContextHierarchyAttributes() to buildContextHierarchyMap() within ContextLoaderUtils. Issue: SPR-10997 --- .../test/context/ContextLoaderUtils.java | 30 ++--- ...ntextLoaderUtilsContextHierarchyTests.java | 113 ++++++++++++++---- 2 files changed, 105 insertions(+), 38 deletions(-) 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 92f5e2c764..031f12c6d3 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/ContextLoaderUtilsContextHierarchyTests.java b/spring-test/src/test/java/org/springframework/test/context/ContextLoaderUtilsContextHierarchyTests.java index 9f59087219..fc512e2dd3 100644 --- a/spring-test/src/test/java/org/springframework/test/context/ContextLoaderUtilsContextHierarchyTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/ContextLoaderUtilsContextHierarchyTests.java @@ -21,6 +21,8 @@ import java.util.List; import java.util.Map; import org.junit.Test; +import org.springframework.context.ApplicationContextInitializer; +import org.springframework.context.ConfigurableApplicationContext; import org.springframework.test.context.support.AnnotationConfigContextLoader; import static org.hamcrest.CoreMatchers.*; @@ -152,29 +154,6 @@ public class ContextLoaderUtilsContextHierarchyTests extends AbstractContextLoad 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); @@ -262,6 +241,58 @@ public class ContextLoaderUtilsContextHierarchyTests extends AbstractContextLoad 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]); + } + // ------------------------------------------------------------------------- @@ -401,4 +432,40 @@ public class ContextLoaderUtilsContextHierarchyTests extends AbstractContextLoad 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 */ + } + + } + }