Retain order of active profiles in the TCF

Ever since @ActiveProfiles was introduced, the declared active profiles
for integration tests have been sorted in order to support unique cache
key generation; however, there are use cases for which the original
ordering should be retained.

For example, Spring Boot's ConfigFileApplicationListener loads
configuration files for active profiles in the order returned by
Environment.getActiveProfiles(), with the assumption that the ordering
matches the order in which the developer declared the active profiles.

This commit maintains the uniqueness of active profiles declared via
@ActiveProfiles but no longer sorts them.

Issue: SPR-12492
This commit is contained in:
Sam Brannen
2015-06-14 23:35:23 +02:00
parent aed523c112
commit 68a704373d
7 changed files with 55 additions and 43 deletions

View File

@@ -141,7 +141,7 @@ public class MergedContextConfigurationTests {
EMPTY_STRING_ARRAY, EMPTY_CLASS_ARRAY, activeProfiles1, loader);
MergedContextConfiguration mergedConfig2 = new MergedContextConfiguration(getClass(),
EMPTY_STRING_ARRAY, EMPTY_CLASS_ARRAY, activeProfiles2, loader);
assertEquals(mergedConfig1.hashCode(), mergedConfig2.hashCode());
assertNotEquals(mergedConfig1.hashCode(), mergedConfig2.hashCode());
}
@Test
@@ -337,7 +337,7 @@ public class MergedContextConfigurationTests {
EMPTY_STRING_ARRAY, EMPTY_CLASS_ARRAY, activeProfiles1, loader);
MergedContextConfiguration mergedConfig2 = new MergedContextConfiguration(getClass(),
EMPTY_STRING_ARRAY, EMPTY_CLASS_ARRAY, activeProfiles2, loader);
assertEquals(mergedConfig1, mergedConfig2);
assertNotEquals(mergedConfig1, mergedConfig2);
}
@Test

View File

@@ -86,14 +86,15 @@ public class ContextCacheTests {
@Test
public void verifyCacheKeyIsBasedOnActiveProfiles() {
loadCtxAndAssertStats(FooBarProfilesTestCase.class, 1, 0, 1);
loadCtxAndAssertStats(FooBarProfilesTestCase.class, 1, 1, 1);
// Profiles {foo, bar} should hash to the same as {bar,foo}
loadCtxAndAssertStats(BarFooProfilesTestCase.class, 1, 2, 1);
loadCtxAndAssertStats(FooBarProfilesTestCase.class, 1, 3, 1);
loadCtxAndAssertStats(FooBarProfilesTestCase.class, 1, 4, 1);
loadCtxAndAssertStats(BarFooProfilesTestCase.class, 1, 5, 1);
loadCtxAndAssertStats(FooBarActiveProfilesResolverTestCase.class, 1, 6, 1);
int size = 0, hit = 0, miss = 0;
loadCtxAndAssertStats(FooBarProfilesTestCase.class, ++size, hit, ++miss);
loadCtxAndAssertStats(FooBarProfilesTestCase.class, size, ++hit, miss);
// Profiles {foo, bar} should not hash to the same as {bar,foo}
loadCtxAndAssertStats(BarFooProfilesTestCase.class, ++size, hit, ++miss);
loadCtxAndAssertStats(FooBarProfilesTestCase.class, size, ++hit, miss);
loadCtxAndAssertStats(FooBarProfilesTestCase.class, size, ++hit, miss);
loadCtxAndAssertStats(BarFooProfilesTestCase.class, size, ++hit, miss);
loadCtxAndAssertStats(FooBarActiveProfilesResolverTestCase.class, size, ++hit, miss);
}
@Test

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2014 the original author or authors.
* Copyright 2002-2015 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.
@@ -164,12 +164,12 @@ abstract class AbstractContextConfigurationUtilsTests {
}
@ContextConfiguration(locations = "/foo.xml", inheritLocations = false)
@ActiveProfiles(profiles = "foo")
@ActiveProfiles("foo")
static class LocationsFoo {
}
@ContextConfiguration(classes = FooConfig.class, inheritLocations = false)
@ActiveProfiles(profiles = "foo")
@ActiveProfiles("foo")
static class ClassesFoo {
}
@@ -198,14 +198,14 @@ abstract class AbstractContextConfigurationUtilsTests {
}
@ContextConfiguration(locations = "/foo.properties", loader = GenericPropertiesContextLoader.class)
@ActiveProfiles(profiles = "foo")
@ActiveProfiles("foo")
static class PropertiesLocationsFoo {
}
// Combining @Configuration classes with a Properties based loader doesn't really make
// sense, but that's OK for unit testing purposes.
@ContextConfiguration(classes = FooConfig.class, loader = GenericPropertiesContextLoader.class)
@ActiveProfiles(profiles = "foo")
@ActiveProfiles("foo")
static class PropertiesClassesFoo {
}

View File

@@ -22,9 +22,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.junit.Test;
@@ -47,27 +45,22 @@ import static org.springframework.test.context.support.ActiveProfilesUtils.*;
public class ActiveProfilesUtilsTests extends AbstractContextConfigurationUtilsTests {
private void assertResolvedProfiles(Class<?> testClass, String... expected) {
assertNotNull(testClass);
assertNotNull(expected);
String[] actual = resolveActiveProfiles(testClass);
Set<String> expectedSet = new HashSet<String>(Arrays.asList(expected));
Set<String> actualSet = new HashSet<String>(Arrays.asList(actual));
assertEquals(expectedSet, actualSet);
assertArrayEquals(expected, resolveActiveProfiles(testClass));
}
@Test
public void resolveActiveProfilesWithoutAnnotation() {
assertArrayEquals(EMPTY_STRING_ARRAY, resolveActiveProfiles(Enigma.class));
assertResolvedProfiles(Enigma.class, EMPTY_STRING_ARRAY);
}
@Test
public void resolveActiveProfilesWithNoProfilesDeclared() {
assertArrayEquals(EMPTY_STRING_ARRAY, resolveActiveProfiles(BareAnnotations.class));
assertResolvedProfiles(BareAnnotations.class, EMPTY_STRING_ARRAY);
}
@Test
public void resolveActiveProfilesWithEmptyProfiles() {
assertArrayEquals(EMPTY_STRING_ARRAY, resolveActiveProfiles(EmptyProfiles.class));
assertResolvedProfiles(EmptyProfiles.class, EMPTY_STRING_ARRAY);
}
@Test
@@ -75,6 +68,11 @@ public class ActiveProfilesUtilsTests extends AbstractContextConfigurationUtilsT
assertResolvedProfiles(DuplicatedProfiles.class, "foo", "bar", "baz");
}
@Test
public void resolveActiveProfilesWithLocalAndInheritedDuplicatedProfiles() {
assertResolvedProfiles(ExtendedDuplicatedProfiles.class, "foo", "bar", "baz", "cat", "dog");
}
@Test
public void resolveActiveProfilesWithLocalAnnotation() {
assertResolvedProfiles(LocationsFoo.class, "foo");
@@ -252,6 +250,10 @@ public class ActiveProfilesUtilsTests extends AbstractContextConfigurationUtilsT
private static class DuplicatedProfiles {
}
@ActiveProfiles({ "cat", "dog", " foo", "bar ", "cat" })
private static class ExtendedDuplicatedProfiles extends DuplicatedProfiles {
}
@ActiveProfiles(profiles = { "dog", "cat" }, inheritProfiles = false)
private static class Animals extends LocationsBar {
}