Preserve ordering of inlined props in @TestPropertySource
The initial implementation for adding inlined properties configured via @TestPropertySource to the context's environment did not preserve the order in which the properties were physically declared. This makes @TestPropertySource a poor testing facility for mimicking the production environment's configuration if the property source mechanism used in production preserves ordering of property names -- which is the case for YAML-based property sources used in Spring Boot, Spring Yarn, etc. This commit addresses this issue by ensuring that the ordering of inlined properties declared via @TestPropertySource is preserved. Specifically, the original functionality has been refactored. extracted from AbstractContextLoader, and moved to TestPropertySourceUtils where it may later be made public for general purpose use in other frameworks. Issue: SPR-12710
This commit is contained in:
@@ -21,7 +21,10 @@ import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.EnumerablePropertySource;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
@@ -29,28 +32,31 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link TestPropertySource @TestPropertySource}
|
||||
* support with an inlined properties.
|
||||
* Integration tests for {@link TestPropertySource @TestPropertySource} support with
|
||||
* inlined properties.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.1
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@TestPropertySource(properties = { "foo = bar", "baz quux", "enigma: 42",
|
||||
"x.y.z = a=b=c", "server.url = http://example.com", "key.value.1: key=value",
|
||||
"key.value.2 key=value", "key.value.3 key:value" })
|
||||
@TestPropertySource(properties = { "", "foo = bar", "baz quux", "enigma: 42", "x.y.z = a=b=c",
|
||||
"server.url = http://example.com", "key.value.1: key=value", "key.value.2 key=value", "key.value.3 key:value" })
|
||||
public class InlinedPropertiesTestPropertySourceTests {
|
||||
|
||||
@Autowired
|
||||
protected Environment env;
|
||||
private Environment env;
|
||||
|
||||
|
||||
@Test
|
||||
public void verifyPropertiesAreAvailableInEnvironment() {
|
||||
public void propertiesAreAvailableInEnvironment() {
|
||||
|
||||
// Simple key/value pairs
|
||||
assertEquals("bar", env.getProperty("foo"));
|
||||
assertEquals("quux", env.getProperty("baz"));
|
||||
assertEquals(42, env.getProperty("enigma", Integer.class).intValue());
|
||||
|
||||
// Values containing key/value delimiters (":", "=", " ")
|
||||
assertEquals("a=b=c", env.getProperty("x.y.z"));
|
||||
assertEquals("http://example.com", env.getProperty("server.url"));
|
||||
assertEquals("key=value", env.getProperty("key.value.1"));
|
||||
@@ -58,6 +64,28 @@ public class InlinedPropertiesTestPropertySourceTests {
|
||||
assertEquals("key:value", env.getProperty("key.value.3"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void propertyNameOrderingIsPreservedInEnvironment() {
|
||||
String[] propertyNames = null;
|
||||
|
||||
ConfigurableEnvironment configurableEnvironment = (ConfigurableEnvironment) env;
|
||||
for (PropertySource<?> propertySource : configurableEnvironment.getPropertySources()) {
|
||||
if (propertySource instanceof EnumerablePropertySource) {
|
||||
EnumerablePropertySource eps = (EnumerablePropertySource) propertySource;
|
||||
if (eps.getName().startsWith("test properties")) {
|
||||
propertyNames = eps.getPropertyNames();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final String[] expectedPropertyNames = new String[] { "foo", "baz", "enigma", "x.y.z", "server.url",
|
||||
"key.value.1", "key.value.2", "key.value.3" };
|
||||
|
||||
assertArrayEquals(expectedPropertyNames, propertyNames);
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -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.
|
||||
@@ -16,10 +16,16 @@
|
||||
|
||||
package org.springframework.test.context.support;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.MutablePropertySources;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
import org.springframework.mock.env.MockPropertySource;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
@@ -113,6 +119,41 @@ public class TestPropertySourceUtilsTests {
|
||||
new String[] { "classpath:/baz.properties" }, new String[] { "key = value" });
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1.5
|
||||
*/
|
||||
@Test
|
||||
@SuppressWarnings("rawtypes")
|
||||
public void emptyInlinedProperty() {
|
||||
ConfigurableEnvironment environment = new MockEnvironment();
|
||||
MutablePropertySources propertySources = environment.getPropertySources();
|
||||
propertySources.remove(MockPropertySource.MOCK_PROPERTIES_PROPERTY_SOURCE_NAME);
|
||||
assertEquals(0, propertySources.size());
|
||||
addInlinedPropertiesToEnvironment(environment, new String[] { " " });
|
||||
assertEquals(1, propertySources.size());
|
||||
assertEquals(0, ((Map) propertySources.iterator().next().getSource()).size());
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1.5
|
||||
*/
|
||||
@Test
|
||||
public void inlinedPropertyWithMalformedUnicodeInValue() {
|
||||
expectedException.expect(IllegalStateException.class);
|
||||
expectedException.expectMessage("Failed to load test environment property");
|
||||
addInlinedPropertiesToEnvironment(new MockEnvironment(), new String[] { "key = \\uZZZZ" });
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1.5
|
||||
*/
|
||||
@Test
|
||||
public void inlinedPropertyWithMultipleKeyValuePairs() {
|
||||
expectedException.expect(IllegalStateException.class);
|
||||
expectedException.expectMessage("Failed to load exactly one test environment property");
|
||||
addInlinedPropertiesToEnvironment(new MockEnvironment(), new String[] { "a=b\nx=y" });
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
|
||||
Reference in New Issue
Block a user