From f6ae300ec319b9a49213b22046a72aa183ea336d Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Tue, 17 Jun 2014 14:55:42 +0200 Subject: [PATCH] Fix parsing of properties in @IntegrationTest This commit reuses the standard behavior provided by Properties for parsing keys rather than parsing the keys ourselves. This provides a consistent features set regardless of where the property is defined. Fixes gh-1110 --- .../test/SpringApplicationContextLoader.java | 29 +++++-- .../SpringApplicationContextLoaderTests.java | 84 +++++++++++++++++++ 2 files changed, 106 insertions(+), 7 deletions(-) create mode 100644 spring-boot/src/test/java/org/springframework/boot/test/SpringApplicationContextLoaderTests.java diff --git a/spring-boot/src/main/java/org/springframework/boot/test/SpringApplicationContextLoader.java b/spring-boot/src/main/java/org/springframework/boot/test/SpringApplicationContextLoader.java index 30f542930b0..d671fc90e9f 100644 --- a/spring-boot/src/main/java/org/springframework/boot/test/SpringApplicationContextLoader.java +++ b/spring-boot/src/main/java/org/springframework/boot/test/SpringApplicationContextLoader.java @@ -16,6 +16,8 @@ package org.springframework.boot.test; +import java.io.IOException; +import java.io.StringReader; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -24,6 +26,7 @@ import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Properties; import java.util.Set; import org.springframework.beans.BeanUtils; @@ -70,6 +73,8 @@ import org.springframework.web.context.support.StandardServletEnvironment; */ public class SpringApplicationContextLoader extends AbstractContextLoader { + private static final String LINE_SEPARATOR = System.getProperty("line.separator"); + @Override public ApplicationContext loadContext(MergedContextConfiguration config) throws Exception { @@ -148,7 +153,7 @@ public class SpringApplicationContextLoader extends AbstractContextLoader { .detectDefaultConfigurationClasses(declaringClass); } - private Map getEnvironmentProperties(MergedContextConfiguration config) { + protected Map getEnvironmentProperties(MergedContextConfiguration config) { Map properties = new LinkedHashMap(); // JMX bean names will clash if the same bean is used in multiple contexts disableJmx(properties); @@ -173,14 +178,24 @@ public class SpringApplicationContextLoader extends AbstractContextLoader { return Collections.singletonMap("server.port", "-1"); } + // Instead of parsing the keys ourselves, we rely on standard handling private Map extractEnvironmentProperties(String[] values) { + StringBuilder sb = new StringBuilder(); + for (String value : values) { + sb.append(value).append(LINE_SEPARATOR); + } + String content = sb.toString(); + Properties props = new Properties(); + try { + props.load(new StringReader(content)); + } + catch (IOException e) { + throw new IllegalStateException("Unexpected could not load properties from '"+content+"'", e); + } + Map properties = new HashMap(); - for (String pair : values) { - int index = pair.indexOf(":"); - index = (index < 0 ? index = pair.indexOf("=") : index); - String key = pair.substring(0, index > 0 ? index : pair.length()); - String value = (index > 0 ? pair.substring(index + 1) : ""); - properties.put(key.trim(), value.trim()); + for (String name: props.stringPropertyNames()) { + properties.put(name, props.getProperty(name)); } return properties; } diff --git a/spring-boot/src/test/java/org/springframework/boot/test/SpringApplicationContextLoaderTests.java b/spring-boot/src/test/java/org/springframework/boot/test/SpringApplicationContextLoaderTests.java new file mode 100644 index 00000000000..c739af82509 --- /dev/null +++ b/spring-boot/src/test/java/org/springframework/boot/test/SpringApplicationContextLoaderTests.java @@ -0,0 +1,84 @@ +/* + * Copyright 2012-2014 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.test; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; + +import java.util.Map; + +import org.junit.Test; + +import org.springframework.test.context.MergedContextConfiguration; + +/** + * Tests for {@link SpringApplicationContextLoader} + * + * @author Stephane Nicoll + */ +public class SpringApplicationContextLoaderTests { + + private final SpringApplicationContextLoader loader = new SpringApplicationContextLoader(); + + @Test + public void environmentPropertiesSimple() { + Map config = getEnvironmentProperties(SimpleConfig.class); + assertKey(config, "key", "myValue"); + assertKey(config, "anotherKey", "anotherValue"); + } + + @Test + public void environmentPropertiesSeparatorInValue() { + Map config = getEnvironmentProperties(SameSeparatorInValue.class); + assertKey(config, "key", "my=Value"); + assertKey(config, "anotherKey", "another:Value"); + } + + @Test + public void environmentPropertiesAnotherSeparatorInValue() { + Map config = getEnvironmentProperties(AnotherSeparatorInValue.class); + assertKey(config, "key", "my:Value"); + assertKey(config, "anotherKey", "another=Value"); + } + + + private Map getEnvironmentProperties(Class testClass) { + MergedContextConfiguration configuration = mock(MergedContextConfiguration.class); + doReturn(testClass).when(configuration).getTestClass(); + + return loader.getEnvironmentProperties(configuration); + } + + private void assertKey(Map actual, String key, Object value) { + assertTrue("Key '" + key + "' not found", actual.containsKey(key)); + assertEquals(value, actual.get(key)); + } + + + @IntegrationTest({"key=myValue", "anotherKey:anotherValue"}) + static class SimpleConfig { + } + + @IntegrationTest({"key=my=Value", "anotherKey:another:Value"}) + static class SameSeparatorInValue { + } + + @IntegrationTest({"key=my:Value", "anotherKey:another=Value"}) + static class AnotherSeparatorInValue { + } + +}