diff --git a/spring-boot/src/main/java/org/springframework/boot/test/IntegrationTest.java b/spring-boot/src/main/java/org/springframework/boot/test/IntegrationTest.java
index 7c3cd2cbbea..12c0988cf9e 100644
--- a/spring-boot/src/main/java/org/springframework/boot/test/IntegrationTest.java
+++ b/spring-boot/src/main/java/org/springframework/boot/test/IntegrationTest.java
@@ -25,7 +25,6 @@ import java.lang.annotation.Target;
import org.springframework.core.env.Environment;
import org.springframework.test.context.TestExecutionListeners;
-import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.context.support.DirtiesContextTestExecutionListener;
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
@@ -42,21 +41,16 @@ import org.springframework.test.context.transaction.TransactionalTestExecutionLi
@Target(ElementType.TYPE)
// Leave out the ServletTestExecutionListener because it only deals with Mock* servlet
// stuff. A real embedded application will not need the mocks.
-@TestExecutionListeners(listeners = { IntegrationTestPropertiesListener.class, DependencyInjectionTestExecutionListener.class,
+@TestExecutionListeners(listeners = { IntegrationTestPropertiesListener.class,
+ DependencyInjectionTestExecutionListener.class,
DirtiesContextTestExecutionListener.class,
TransactionalTestExecutionListener.class })
-@TestPropertySource
public @interface IntegrationTest {
- /**
- * Synonym for properties().
- */
- String[] value() default {};
-
/**
* Properties in form {@literal key=value} that should be added to the Spring
* {@link Environment} before the test runs.
*/
- String[] properties() default {"server.port=-1", "spring.jmx.enabled=false"};
+ String[] value() default {};
}
diff --git a/spring-boot/src/main/java/org/springframework/boot/test/IntegrationTestPropertiesListener.java b/spring-boot/src/main/java/org/springframework/boot/test/IntegrationTestPropertiesListener.java
index c5a8a67a50b..54582ef5010 100644
--- a/spring-boot/src/main/java/org/springframework/boot/test/IntegrationTestPropertiesListener.java
+++ b/spring-boot/src/main/java/org/springframework/boot/test/IntegrationTestPropertiesListener.java
@@ -19,96 +19,59 @@ import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
-import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.core.annotation.AnnotatedElementUtils;
+import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.test.context.MergedContextConfiguration;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.support.AbstractTestExecutionListener;
import org.springframework.test.util.ReflectionTestUtils;
/**
- * Manipulate the TestContext to merge properties from @IntegrationTest
value
- * and properties attributes.
- *
- * @author Dave Syer
+ * Manipulate the TestContext to merge properties from {@code @IntegrationTest}.
*
+ * @author Dave Syer
+ * @author Phillip Webb
+ * @since 1.2.0
*/
-public class IntegrationTestPropertiesListener extends AbstractTestExecutionListener {
+class IntegrationTestPropertiesListener extends AbstractTestExecutionListener {
- private String[] defaultValues = (String[]) AnnotationUtils.getDefaultValue(
- IntegrationTest.class, "properties");
+ private static final String ANNOTATION_TYPE = IntegrationTest.class.getName();
@Override
public void prepareTestInstance(TestContext testContext) throws Exception {
- MergedContextConfiguration config = null;
+ Class> testClass = testContext.getTestClass();
+ if (AnnotatedElementUtils.isAnnotated(testClass, ANNOTATION_TYPE)) {
+ AnnotationAttributes annotationAttributes = AnnotatedElementUtils
+ .getAnnotationAttributes(testClass, ANNOTATION_TYPE);
+ addPropertySourceProperties(testContext,
+ annotationAttributes.getStringArray("value"));
+ }
+ }
+
+ private void addPropertySourceProperties(TestContext testContext, String[] properties) {
try {
- // Here be hacks...
- config = (MergedContextConfiguration) ReflectionTestUtils.getField(
- testContext, "mergedContextConfiguration");
- ReflectionTestUtils.setField(config, "propertySourceProperties",
- getEnvironmentProperties(config));
+ addPropertySourcePropertiesUsingReflection(testContext, properties);
}
- catch (IllegalStateException e) {
- throw e;
+ catch (RuntimeException ex) {
+ throw ex;
}
- catch (Exception e) {
+ catch (Exception ex) {
+ throw new IllegalStateException(ex);
}
}
- protected String[] getEnvironmentProperties(MergedContextConfiguration config) {
- IntegrationTest annotation = AnnotationUtils.findAnnotation(
- config.getTestClass(), IntegrationTest.class);
- return mergeProperties(
- getDefaultEnvironmentProperties(config.getPropertySourceProperties(),
- annotation), getEnvironmentProperties(annotation));
- }
-
- private String[] getDefaultEnvironmentProperties(String[] original,
- IntegrationTest annotation) {
- String[] defaults = mergeProperties(original, defaultValues);
- if (annotation == null || defaults.length == 0) {
- // Without an @IntegrationTest we can assume the defaults are fine
- return defaults;
+ private void addPropertySourcePropertiesUsingReflection(TestContext testContext,
+ String[] properties) throws Exception {
+ if (properties.length == 0) {
+ return;
}
- // If @IntegrationTest is present we don't provide a default for the server.port
- return filterPorts((String[]) AnnotationUtils.getDefaultValue(annotation,
- "properties"));
- }
-
- private String[] filterPorts(String[] values) {
-
- Set result = new LinkedHashSet();
- for (String value : values) {
- if (!value.contains(".port")) {
- result.add(value);
- }
- }
- return result.toArray(new String[0]);
-
- }
-
- private String[] getEnvironmentProperties(IntegrationTest annotation) {
- if (annotation == null) {
- return new String[0];
- }
- if (Arrays.asList(annotation.properties()).equals(Arrays.asList(defaultValues))) {
- return annotation.value();
- }
- if (annotation.value().length == 0) {
- return annotation.properties();
- }
- throw new IllegalStateException(
- "Either properties or value can be provided but not both");
- }
-
- private String[] mergeProperties(String[] original, String[] extra) {
- Set result = new LinkedHashSet();
- for (String value : original) {
- result.add(value);
- }
- for (String value : extra) {
- result.add(value);
- }
- return result.toArray(new String[0]);
+ MergedContextConfiguration configuration = (MergedContextConfiguration) ReflectionTestUtils
+ .getField(testContext, "mergedContextConfiguration");
+ Set merged = new LinkedHashSet((Arrays.asList(configuration
+ .getPropertySourceProperties())));
+ merged.addAll(Arrays.asList(properties));
+ ReflectionTestUtils.setField(configuration, "propertySourceProperties",
+ merged.toArray(new String[merged.size()]));
}
}
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 38976740f0a..8bd50579afe 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
@@ -20,7 +20,8 @@ import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashMap;
+import java.util.Collections;
+import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
@@ -90,7 +91,7 @@ public class SpringApplicationContextLoader extends AbstractContextLoader {
.addAfter(
StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME,
new MapPropertySource("integrationTest",
- extractEnvironmentProperties(config.getPropertySourceProperties())));
+ getEnvironmentProperties(config)));
application.setEnvironment(environment);
List> initializers = getInitializers(config,
application);
@@ -101,36 +102,9 @@ public class SpringApplicationContextLoader extends AbstractContextLoader {
application.setWebEnvironment(false);
}
application.setInitializers(initializers);
-
return application.run();
}
- // Instead of parsing the keys ourselves, we rely on standard handling
- protected Map extractEnvironmentProperties(String[] values) {
- Map properties = new HashMap();
- if (values==null) {
- return properties;
- }
- 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);
- }
-
- for (String name : props.stringPropertyNames()) {
- properties.put(name, props.getProperty(name));
- }
- return properties;
- }
-
@Override
public void processContextConfiguration(
ContextConfigurationAttributes configAttributes) {
@@ -176,8 +150,52 @@ public class SpringApplicationContextLoader extends AbstractContextLoader {
return AnnotationConfigContextLoaderUtils
.detectDefaultConfigurationClasses(declaringClass);
}
-
-
+
+ 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);
+ properties.putAll(extractEnvironmentProperties(config
+ .getPropertySourceProperties()));
+ if (AnnotationUtils.findAnnotation(config.getTestClass(), IntegrationTest.class) == null) {
+ properties.putAll(getDefaultEnvironmentProperties());
+ }
+ return properties;
+ }
+
+ private void disableJmx(Map properties) {
+ properties.put("spring.jmx.enabled", "false");
+ }
+
+ private Map getDefaultEnvironmentProperties() {
+ return Collections.singletonMap("server.port", "-1");
+ }
+
+ Map extractEnvironmentProperties(String[] values) {
+ // Instead of parsing the keys ourselves, we rely on standard handling
+ if (values == null) {
+ return Collections.emptyMap();
+ }
+ String content = StringUtils.arrayToDelimitedString(values, LINE_SEPARATOR);
+ Properties properties = new Properties();
+ try {
+ properties.load(new StringReader(content));
+ return asMap(properties);
+ }
+ catch (IOException ex) {
+ throw new IllegalStateException("Unexpected could not load properties from '"
+ + content + "'", ex);
+ }
+ }
+
+ private Map asMap(Properties properties) {
+ Map map = new LinkedHashMap();
+ for (String name : properties.stringPropertyNames()) {
+ map.put(name, properties.getProperty(name));
+ }
+ return map;
+ }
private List> getInitializers(
MergedContextConfiguration mergedConfig, SpringApplication application) {
diff --git a/spring-boot/src/test/java/org/springframework/boot/test/SpringApplicationConfigurationJmxTests.java b/spring-boot/src/test/java/org/springframework/boot/test/SpringApplicationConfigurationJmxTests.java
index 8a1df6fcf3d..4ce9cf4dfce 100644
--- a/spring-boot/src/test/java/org/springframework/boot/test/SpringApplicationConfigurationJmxTests.java
+++ b/spring-boot/src/test/java/org/springframework/boot/test/SpringApplicationConfigurationJmxTests.java
@@ -16,8 +16,6 @@
package org.springframework.boot.test;
-import static org.junit.Assert.assertFalse;
-
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Value;
@@ -27,6 +25,8 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import static org.junit.Assert.assertFalse;
+
/**
* Tests for disabling JMX by default
*
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
index 426bda8b14b..8812e12a29f 100644
--- a/spring-boot/src/test/java/org/springframework/boot/test/SpringApplicationContextLoaderTests.java
+++ b/spring-boot/src/test/java/org/springframework/boot/test/SpringApplicationContextLoaderTests.java
@@ -16,9 +16,6 @@
package org.springframework.boot.test;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
import java.util.Map;
import org.junit.Test;
@@ -27,6 +24,9 @@ import org.springframework.test.context.TestContext;
import org.springframework.test.context.TestContextManager;
import org.springframework.test.util.ReflectionTestUtils;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
/**
* Tests for {@link SpringApplicationContextLoader}
*
@@ -43,24 +43,12 @@ public class SpringApplicationContextLoaderTests {
assertKey(config, "anotherKey", "anotherValue");
}
- @Test
- public void environmentPropertiesDefaults() throws Exception {
- Map config = getEnvironmentProperties(SimpleConfig.class);
- assertMissingKey(config, "server.port");
- assertKey(config, "spring.jmx.enabled", "false");
- }
-
@Test
public void environmentPropertiesOverrideDefaults() throws Exception {
Map config = getEnvironmentProperties(OverrideConfig.class);
assertKey(config, "server.port", "2345");
}
- @Test(expected=IllegalStateException.class)
- public void environmentPropertiesIllegal() throws Exception {
- getEnvironmentProperties(IllegalConfig.class);
- }
-
@Test
public void environmentPropertiesAppend() throws Exception {
Map config = getEnvironmentProperties(AppendConfig.class);
@@ -82,12 +70,15 @@ public class SpringApplicationContextLoaderTests {
assertKey(config, "anotherKey", "another=Value");
}
- private Map getEnvironmentProperties(Class> testClass) throws Exception {
- TestContext context = new ExposedTestContextManager(testClass).getExposedTestContext();
+ private Map getEnvironmentProperties(Class> testClass)
+ throws Exception {
+ TestContext context = new ExposedTestContextManager(testClass)
+ .getExposedTestContext();
new IntegrationTestPropertiesListener().prepareTestInstance(context);
- MergedContextConfiguration config = (MergedContextConfiguration) ReflectionTestUtils.getField(
- context, "mergedContextConfiguration");
- return this.loader.extractEnvironmentProperties(config.getPropertySourceProperties());
+ MergedContextConfiguration config = (MergedContextConfiguration) ReflectionTestUtils
+ .getField(context, "mergedContextConfiguration");
+ return this.loader.extractEnvironmentProperties(config
+ .getPropertySourceProperties());
}
private void assertKey(Map actual, String key, Object value) {
@@ -95,10 +86,6 @@ public class SpringApplicationContextLoaderTests {
assertEquals(value, actual.get(key));
}
- private void assertMissingKey(Map actual, String key) {
- assertTrue("Key '" + key + "' found", !actual.containsKey(key));
- }
-
@IntegrationTest({ "key=myValue", "anotherKey:anotherValue" })
static class SimpleConfig {
}
@@ -107,11 +94,7 @@ public class SpringApplicationContextLoaderTests {
static class OverrideConfig {
}
- @IntegrationTest(value = { "key=aValue", "anotherKey:anotherValue" }, properties = { "key=myValue", "otherKey=otherValue" })
- static class IllegalConfig {
- }
-
- @IntegrationTest(properties = { "key=myValue", "otherKey=otherValue" })
+ @IntegrationTest({ "key=myValue", "otherKey=otherValue" })
static class AppendConfig {
}
@@ -122,18 +105,20 @@ public class SpringApplicationContextLoaderTests {
@IntegrationTest({ "key=my:Value", "anotherKey:another=Value" })
static class AnotherSeparatorInValue {
}
-
+
+ /**
+ * {@link TestContextManager} which exposes the {@link TestContext}.
+ */
private static class ExposedTestContextManager extends TestContextManager {
public ExposedTestContextManager(Class> testClass) {
super(testClass);
}
-
+
public final TestContext getExposedTestContext() {
return super.getTestContext();
}
-
-
+
}
}