diff --git a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/SpringBootTestRandomPortEnvironmentPostProcessor.java b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/SpringBootTestRandomPortEnvironmentPostProcessor.java index 9f97d871bc6..1055005ec3f 100644 --- a/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/SpringBootTestRandomPortEnvironmentPostProcessor.java +++ b/spring-boot-project/spring-boot-test/src/main/java/org/springframework/boot/test/web/SpringBootTestRandomPortEnvironmentPostProcessor.java @@ -19,7 +19,7 @@ import java.util.Objects; import org.springframework.boot.SpringApplication; import org.springframework.boot.env.EnvironmentPostProcessor; -import org.springframework.core.convert.ConversionService; +import org.springframework.core.convert.ConversionFailedException; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.MapPropertySource; import org.springframework.core.env.PropertySource; @@ -46,8 +46,7 @@ class SpringBootTestRandomPortEnvironmentPostProcessor SpringApplication application) { MapPropertySource source = (MapPropertySource) environment.getPropertySources() .get(TestPropertySourceUtils.INLINED_PROPERTIES_PROPERTY_SOURCE_NAME); - if (source == null - || isTestServerPortFixed(source, environment.getConversionService()) + if (source == null || isTestServerPortFixed(source, environment) || isTestManagementPortConfigured(source)) { return; } @@ -67,9 +66,9 @@ class SpringBootTestRandomPortEnvironmentPostProcessor } private boolean isTestServerPortFixed(MapPropertySource source, - ConversionService conversionService) { - return !Integer.valueOf(0).equals( - getPropertyAsInteger(source, SERVER_PORT_PROPERTY, conversionService)); + ConfigurableEnvironment environment) { + return !Integer.valueOf(0) + .equals(getPropertyAsInteger(source, SERVER_PORT_PROPERTY, environment)); } private boolean isTestManagementPortConfigured(PropertySource source) { @@ -81,13 +80,12 @@ class SpringBootTestRandomPortEnvironmentPostProcessor return environment.getPropertySources().stream() .filter((source) -> !source.getName().equals( TestPropertySourceUtils.INLINED_PROPERTIES_PROPERTY_SOURCE_NAME)) - .map((source) -> getPropertyAsInteger(source, property, - environment.getConversionService())) + .map((source) -> getPropertyAsInteger(source, property, environment)) .filter(Objects::nonNull).findFirst().orElse(defaultValue); } private Integer getPropertyAsInteger(PropertySource source, String property, - ConversionService conversionService) { + ConfigurableEnvironment environment) { Object value = source.getProperty(property); if (value == null) { return null; @@ -95,7 +93,21 @@ class SpringBootTestRandomPortEnvironmentPostProcessor if (ClassUtils.isAssignableValue(Integer.class, value)) { return (Integer) value; } - return conversionService.convert(value, Integer.class); + try { + return environment.getConversionService().convert(value, Integer.class); + } + catch (ConversionFailedException ex) { + if (ClassUtils.isAssignable(value.getClass(), String.class)) { + return getResolvedValueIfPossible(environment, (String) value); + } + throw ex; + } + } + + private Integer getResolvedValueIfPossible(ConfigurableEnvironment environment, + String value) { + String resolvedValue = environment.resolveRequiredPlaceholders(value); + return environment.getConversionService().convert(resolvedValue, Integer.class); } } diff --git a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/SpringBootTestRandomPortEnvironmentPostProcessorTests.java b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/SpringBootTestRandomPortEnvironmentPostProcessorTests.java index b91bcee9707..4b7727f68d0 100644 --- a/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/SpringBootTestRandomPortEnvironmentPostProcessorTests.java +++ b/spring-boot-project/spring-boot-test/src/test/java/org/springframework/boot/test/web/SpringBootTestRandomPortEnvironmentPostProcessorTests.java @@ -28,6 +28,7 @@ import org.springframework.mock.env.MockEnvironment; import org.springframework.test.context.support.TestPropertySourceUtils; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; /** * Tests for {@link SpringBootTestRandomPortEnvironmentPostProcessor}. @@ -141,6 +142,56 @@ public class SpringBootTestRandomPortEnvironmentPostProcessorTests { assertThat(this.environment.getProperty("management.server.port")).isEqualTo("0"); } + @Test + public void postProcessWhenManagementServerPortPlaceholderPresentShouldResolvePlaceholder() { + addTestPropertySource("0", null); + MapPropertySource testPropertySource = (MapPropertySource) this.propertySources + .get(TestPropertySourceUtils.INLINED_PROPERTIES_PROPERTY_SOURCE_NAME); + testPropertySource.getSource().put("port", "9090"); + this.propertySources.addLast(new MapPropertySource("other", + Collections.singletonMap("management.server.port", "${port}"))); + this.postProcessor.postProcessEnvironment(this.environment, null); + assertThat(this.environment.getProperty("server.port")).isEqualTo("0"); + assertThat(this.environment.getProperty("management.server.port")).isEqualTo("0"); + } + + @Test + public void postProcessWhenManagementServerPortPlaceholderAbsentShouldFail() { + addTestPropertySource("0", null); + this.propertySources.addLast(new MapPropertySource("other", + Collections.singletonMap("management.server.port", "${port}"))); + assertThatIllegalArgumentException().isThrownBy( + () -> this.postProcessor.postProcessEnvironment(this.environment, null)) + .withMessage("Could not resolve placeholder 'port' in value \"${port}\""); + } + + @Test + public void postProcessWhenServerPortPlaceholderPresentShouldResolvePlaceholder() { + addTestPropertySource("0", null); + MapPropertySource testPropertySource = (MapPropertySource) this.propertySources + .get(TestPropertySourceUtils.INLINED_PROPERTIES_PROPERTY_SOURCE_NAME); + testPropertySource.getSource().put("port", "8080"); + Map source = new HashMap<>(); + source.put("server.port", "${port}"); + source.put("management.server.port", "9090"); + this.propertySources.addLast(new MapPropertySource("other", source)); + this.postProcessor.postProcessEnvironment(this.environment, null); + assertThat(this.environment.getProperty("server.port")).isEqualTo("0"); + assertThat(this.environment.getProperty("management.server.port")).isEqualTo("0"); + } + + @Test + public void postProcessWhenServerPortPlaceholderAbsentShouldFail() { + addTestPropertySource("0", null); + Map source = new HashMap<>(); + source.put("server.port", "${port}"); + source.put("management.server.port", "9090"); + this.propertySources.addLast(new MapPropertySource("other", source)); + assertThatIllegalArgumentException().isThrownBy( + () -> this.postProcessor.postProcessEnvironment(this.environment, null)) + .withMessage("Could not resolve placeholder 'port' in value \"${port}\""); + } + private void addTestPropertySource(String serverPort, String managementPort) { Map source = new HashMap<>(); source.put("server.port", serverPort);