Skip to content

Commit 63de2fa

Browse files
committed
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-11011 Backport-Commit: 7658d85
1 parent 5d8aa63 commit 63de2fa

File tree

2 files changed

+103
-38
lines changed

2 files changed

+103
-38
lines changed

spring-test/src/main/java/org/springframework/test/context/ContextLoaderUtils.java

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -237,11 +237,9 @@ private static void convertContextConfigToConfigAttributesAndAddToList(ContextCo
237237
* never {@code null}
238238
* @throws IllegalArgumentException if the supplied class is {@code null}; if
239239
* neither {@code @ContextConfiguration} nor {@code @ContextHierarchy} is
240-
* <em>present</em> on the supplied class; if a given class in the class hierarchy
240+
* <em>present</em> on the supplied class; or if a given class in the class hierarchy
241241
* declares both {@code @ContextConfiguration} and {@code @ContextHierarchy} as
242-
* top-level annotations; or if individual {@code @ContextConfiguration}
243-
* elements within a {@code @ContextHierarchy} declaration on a given class
244-
* in the class hierarchy do not define unique context configuration.
242+
* top-level annotations.
245243
*
246244
* @since 3.2.2
247245
* @see #buildContextHierarchyMap(Class)
@@ -287,17 +285,6 @@ else if (contextHierarchyDeclaredLocally) {
287285
convertContextConfigToConfigAttributesAndAddToList(contextConfiguration, declaringClass,
288286
configAttributesList);
289287
}
290-
291-
// Check for uniqueness
292-
Set<ContextConfigurationAttributes> configAttributesSet = new HashSet<ContextConfigurationAttributes>(
293-
configAttributesList);
294-
if (configAttributesSet.size() != configAttributesList.size()) {
295-
String msg = String.format("The @ContextConfiguration elements configured via "
296-
+ "@ContextHierarchy in test class [%s] must define unique contexts to load.",
297-
declaringClass.getName());
298-
logger.error(msg);
299-
throw new IllegalStateException(msg);
300-
}
301288
}
302289
else {
303290
// This should theoretically actually never happen...
@@ -336,6 +323,9 @@ else if (contextHierarchyDeclaredLocally) {
336323
* (must not be {@code null})
337324
* @return a map of context configuration attributes for the context hierarchy,
338325
* keyed by context hierarchy level name; never {@code null}
326+
* @throws IllegalArgumentException if the lists of context configuration
327+
* attributes for each level in the {@code @ContextHierarchy} do not define
328+
* unique context configuration within the overall hierarchy.
339329
*
340330
* @since 3.2.2
341331
* @see #resolveContextHierarchyAttributes(Class)
@@ -363,6 +353,16 @@ static Map<String, List<ContextConfigurationAttributes>> buildContextHierarchyMa
363353
}
364354
}
365355

356+
// Check for uniqueness
357+
Set<List<ContextConfigurationAttributes>> set = new HashSet<List<ContextConfigurationAttributes>>(map.values());
358+
if (set.size() != map.size()) {
359+
String msg = String.format("The @ContextConfiguration elements configured via "
360+
+ "@ContextHierarchy in test class [%s] and its superclasses must "
361+
+ "define unique contexts per hierarchy level.", testClass.getName());
362+
logger.error(msg);
363+
throw new IllegalStateException(msg);
364+
}
365+
366366
return map;
367367
}
368368

spring-test/src/test/java/org/springframework/test/context/ContextLoaderUtilsTests.java

Lines changed: 88 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -225,29 +225,6 @@ public void resolveContextHierarchyAttributesForTestClassHierarchyWithMultiLevel
225225
assertThat(configAttributesListClassLevel3.get(2).getLocations()[0], equalTo("3-C.xml"));
226226
}
227227

228-
private void assertContextConfigEntriesAreNotUnique(Class<?> testClass) {
229-
try {
230-
resolveContextHierarchyAttributes(testClass);
231-
fail("Should throw an IllegalStateException");
232-
}
233-
catch (IllegalStateException e) {
234-
String msg = String.format(
235-
"The @ContextConfiguration elements configured via @ContextHierarchy in test class [%s] must define unique contexts to load.",
236-
testClass.getName());
237-
assertEquals(msg, e.getMessage());
238-
}
239-
}
240-
241-
@Test
242-
public void resolveContextHierarchyAttributesForSingleTestClassWithMultiLevelContextHierarchyWithEmptyContextConfig() {
243-
assertContextConfigEntriesAreNotUnique(SingleTestClassWithMultiLevelContextHierarchyWithEmptyContextConfig.class);
244-
}
245-
246-
@Test
247-
public void resolveContextHierarchyAttributesForSingleTestClassWithMultiLevelContextHierarchyWithDuplicatedContextConfig() {
248-
assertContextConfigEntriesAreNotUnique(SingleTestClassWithMultiLevelContextHierarchyWithDuplicatedContextConfig.class);
249-
}
250-
251228
@Test
252229
public void buildContextHierarchyMapForTestClassHierarchyWithMultiLevelContextHierarchies() {
253230
Map<String, List<ContextConfigurationAttributes>> map = buildContextHierarchyMap(TestClass3WithMultiLevelContextHierarchy.class);
@@ -335,6 +312,58 @@ public void buildContextHierarchyMapForTestClassHierarchyWithMultiLevelContextHi
335312
assertThat(level3Config.get(0).getLocations()[0], is("2-C.xml"));
336313
}
337314

315+
private void assertContextConfigEntriesAreNotUnique(Class<?> testClass) {
316+
try {
317+
buildContextHierarchyMap(testClass);
318+
fail("Should throw an IllegalStateException");
319+
}
320+
catch (IllegalStateException e) {
321+
String msg = String.format(
322+
"The @ContextConfiguration elements configured via @ContextHierarchy in test class [%s] and its superclasses must define unique contexts per hierarchy level.",
323+
testClass.getName());
324+
assertEquals(msg, e.getMessage());
325+
}
326+
}
327+
328+
@Test
329+
public void buildContextHierarchyMapForSingleTestClassWithMultiLevelContextHierarchyWithEmptyContextConfig() {
330+
assertContextConfigEntriesAreNotUnique(SingleTestClassWithMultiLevelContextHierarchyWithEmptyContextConfig.class);
331+
}
332+
333+
@Test
334+
public void buildContextHierarchyMapForSingleTestClassWithMultiLevelContextHierarchyWithDuplicatedContextConfig() {
335+
assertContextConfigEntriesAreNotUnique(SingleTestClassWithMultiLevelContextHierarchyWithDuplicatedContextConfig.class);
336+
}
337+
338+
/**
339+
* Used to reproduce bug reported in https://jira.springsource.org/browse/SPR-10997
340+
*/
341+
@Test
342+
public void buildContextHierarchyMapForTestClassHierarchyWithMultiLevelContextHierarchiesAndOverriddenInitializers() {
343+
Map<String, List<ContextConfigurationAttributes>> map = buildContextHierarchyMap(TestClass2WithMultiLevelContextHierarchyWithOverriddenInitializers.class);
344+
345+
assertThat(map.size(), is(2));
346+
assertThat(map.keySet(), hasItems("alpha", "beta"));
347+
348+
List<ContextConfigurationAttributes> alphaConfig = map.get("alpha");
349+
assertThat(alphaConfig.size(), is(2));
350+
assertThat(alphaConfig.get(0).getLocations().length, is(1));
351+
assertThat(alphaConfig.get(0).getLocations()[0], is("1-A.xml"));
352+
assertThat(alphaConfig.get(0).getInitializers().length, is(0));
353+
assertThat(alphaConfig.get(1).getLocations().length, is(0));
354+
assertThat(alphaConfig.get(1).getInitializers().length, is(1));
355+
assertEquals(DummyApplicationContextInitializer.class, alphaConfig.get(1).getInitializers()[0]);
356+
357+
List<ContextConfigurationAttributes> betaConfig = map.get("beta");
358+
assertThat(betaConfig.size(), is(2));
359+
assertThat(betaConfig.get(0).getLocations().length, is(1));
360+
assertThat(betaConfig.get(0).getLocations()[0], is("1-B.xml"));
361+
assertThat(betaConfig.get(0).getInitializers().length, is(0));
362+
assertThat(betaConfig.get(1).getLocations().length, is(0));
363+
assertThat(betaConfig.get(1).getInitializers().length, is(1));
364+
assertEquals(DummyApplicationContextInitializer.class, betaConfig.get(1).getInitializers()[0]);
365+
}
366+
338367
@Test(expected = IllegalStateException.class)
339368
public void resolveConfigAttributesWithConflictingLocations() {
340369
resolveContextConfigurationAttributes(ConflictingLocations.class);
@@ -843,4 +872,40 @@ private static class SingleTestClassWithMultiLevelContextHierarchyWithEmptyConte
843872
private static class SingleTestClassWithMultiLevelContextHierarchyWithDuplicatedContextConfig {
844873
}
845874

875+
/**
876+
* Used to reproduce bug reported in https://jira.springsource.org/browse/SPR-10997
877+
*/
878+
@ContextHierarchy({//
879+
//
880+
@ContextConfiguration(name = "alpha", locations = "1-A.xml"),//
881+
@ContextConfiguration(name = "beta", locations = "1-B.xml") //
882+
})
883+
private static class TestClass1WithMultiLevelContextHierarchyWithUniqueContextConfig {
884+
}
885+
886+
/**
887+
* Used to reproduce bug reported in https://jira.springsource.org/browse/SPR-10997
888+
*/
889+
@ContextHierarchy({//
890+
//
891+
@ContextConfiguration(name = "alpha", initializers = DummyApplicationContextInitializer.class),//
892+
@ContextConfiguration(name = "beta", initializers = DummyApplicationContextInitializer.class) //
893+
})
894+
private static class TestClass2WithMultiLevelContextHierarchyWithOverriddenInitializers extends
895+
TestClass1WithMultiLevelContextHierarchyWithUniqueContextConfig {
896+
}
897+
898+
/**
899+
* Used to reproduce bug reported in https://jira.springsource.org/browse/SPR-10997
900+
*/
901+
private static class DummyApplicationContextInitializer implements
902+
ApplicationContextInitializer<ConfigurableApplicationContext> {
903+
904+
@Override
905+
public void initialize(ConfigurableApplicationContext applicationContext) {
906+
/* no-op */
907+
}
908+
909+
}
910+
846911
}

0 commit comments

Comments
 (0)