Browse Source

Merge branch '4.0.x'

Closes gh-48654
pull/48667/head
Stéphane Nicoll 1 month ago
parent
commit
754a3aa2ab
  1. 34
      module/spring-boot-web-server/src/main/java/org/springframework/boot/web/server/context/SpringBootTestRandomPortContextCustomizer.java
  2. 27
      module/spring-boot-web-server/src/main/java/org/springframework/boot/web/server/context/SpringBootTestRandomPortContextCustomizerFactory.java
  3. 34
      module/spring-boot-web-server/src/test/java/org/springframework/boot/web/server/context/SpringBootTestRandomPortContextCustomizerTests.java
  4. 65
      smoke-test/spring-boot-smoke-test-actuator/src/test/java/smoketest/actuator/ManagementRandomPortWithConfiguredPortSampleActuatorApplicationTests.java

34
module/spring-boot-web-server/src/main/java/org/springframework/boot/web/server/context/SpringBootTestRandomPortApplicationListener.java → module/spring-boot-web-server/src/main/java/org/springframework/boot/web/server/context/SpringBootTestRandomPortContextCustomizer.java

@ -20,10 +20,8 @@ import java.util.Objects;
import org.jspecify.annotations.Nullable; import org.jspecify.annotations.Nullable;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.event.SmartApplicationListener; import org.springframework.context.event.SmartApplicationListener;
import org.springframework.core.Ordered;
import org.springframework.core.convert.ConversionFailedException; import org.springframework.core.convert.ConversionFailedException;
import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.ConversionService;
import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.ConfigurableEnvironment;
@ -33,6 +31,8 @@ import org.springframework.core.env.PropertyResolver;
import org.springframework.core.env.PropertySource; import org.springframework.core.env.PropertySource;
import org.springframework.core.env.PropertySources; import org.springframework.core.env.PropertySources;
import org.springframework.lang.Contract; import org.springframework.lang.Contract;
import org.springframework.test.context.ContextCustomizer;
import org.springframework.test.context.MergedContextConfiguration;
import org.springframework.test.context.support.TestPropertySourceUtils; import org.springframework.test.context.support.TestPropertySourceUtils;
import org.springframework.util.ClassUtils; import org.springframework.util.ClassUtils;
@ -45,25 +45,13 @@ import org.springframework.util.ClassUtils;
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Phillip Webb * @author Phillip Webb
*/ */
class SpringBootTestRandomPortApplicationListener implements SmartApplicationListener, Ordered { class SpringBootTestRandomPortContextCustomizer implements ContextCustomizer {
private static final String TEST_SOURCE_NAME = TestPropertySourceUtils.INLINED_PROPERTIES_PROPERTY_SOURCE_NAME; private static final String TEST_SOURCE_NAME = TestPropertySourceUtils.INLINED_PROPERTIES_PROPERTY_SOURCE_NAME;
@Override @Override
public int getOrder() { public void customizeContext(ConfigurableApplicationContext context, MergedContextConfiguration mergedConfig) {
return Ordered.LOWEST_PRECEDENCE; postProcessEnvironment(context.getEnvironment());
}
@Override
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
return ApplicationEnvironmentPreparedEvent.class.isAssignableFrom(eventType);
}
@Override
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ApplicationEnvironmentPreparedEvent environmentPreparedEvent) {
postProcessEnvironment(environmentPreparedEvent.getEnvironment());
}
} }
void postProcessEnvironment(ConfigurableEnvironment environment) { void postProcessEnvironment(ConfigurableEnvironment environment) {
@ -92,6 +80,16 @@ class SpringBootTestRandomPortApplicationListener implements SmartApplicationLis
return (!managementPort.equals(serverPort)) ? "0" : ""; return (!managementPort.equals(serverPort)) ? "0" : "";
} }
@Override
public boolean equals(Object obj) {
return (obj != null) && (obj.getClass() == getClass());
}
@Override
public int hashCode() {
return getClass().hashCode();
}
private enum Port { private enum Port {
SERVER("server.port"), MANAGEMENT("management.server.port"); SERVER("server.port"), MANAGEMENT("management.server.port");

27
module/spring-boot-web-server/src/main/java/org/springframework/boot/web/server/context/SpringBootTestRandomPortContextCustomizerFactory.java

@ -20,15 +20,13 @@ import java.util.List;
import org.jspecify.annotations.Nullable; import org.jspecify.annotations.Nullable;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.test.context.ContextConfigurationAttributes; import org.springframework.test.context.ContextConfigurationAttributes;
import org.springframework.test.context.ContextCustomizer; import org.springframework.test.context.ContextCustomizer;
import org.springframework.test.context.ContextCustomizerFactory; import org.springframework.test.context.ContextCustomizerFactory;
import org.springframework.test.context.MergedContextConfiguration;
/** /**
* {@link ContextCustomizerFactory} apply * {@link ContextCustomizerFactory} implementation to apply
* {@link SpringBootTestRandomPortApplicationListener} to tests. * {@link SpringBootTestRandomPortContextCustomizer} to tests.
* *
* @author Phillip Webb * @author Phillip Webb
*/ */
@ -37,26 +35,7 @@ class SpringBootTestRandomPortContextCustomizerFactory implements ContextCustomi
@Override @Override
public @Nullable ContextCustomizer createContextCustomizer(Class<?> testClass, public @Nullable ContextCustomizer createContextCustomizer(Class<?> testClass,
List<ContextConfigurationAttributes> configAttributes) { List<ContextConfigurationAttributes> configAttributes) {
return new Customizer(); return new SpringBootTestRandomPortContextCustomizer();
}
static class Customizer implements ContextCustomizer {
@Override
public void customizeContext(ConfigurableApplicationContext context, MergedContextConfiguration mergedConfig) {
context.addApplicationListener(new SpringBootTestRandomPortApplicationListener());
}
@Override
public boolean equals(Object obj) {
return (obj != null) && (obj.getClass() == getClass());
}
@Override
public int hashCode() {
return getClass().hashCode();
}
} }
} }

34
module/spring-boot-web-server/src/test/java/org/springframework/boot/web/server/context/SpringBootTestRandomPortApplicationListenerTests.java → module/spring-boot-web-server/src/test/java/org/springframework/boot/web/server/context/SpringBootTestRandomPortContextCustomizerTests.java

@ -34,14 +34,14 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
/** /**
* Tests for {@link SpringBootTestRandomPortApplicationListener}. * Tests for {@link SpringBootTestRandomPortContextCustomizer}.
* *
* @author Madhura Bhave * @author Madhura Bhave
* @author Andy Wilkinson * @author Andy Wilkinson
*/ */
class SpringBootTestRandomPortApplicationListenerTests { class SpringBootTestRandomPortContextCustomizerTests {
private final SpringBootTestRandomPortApplicationListener listener = new SpringBootTestRandomPortApplicationListener(); private final SpringBootTestRandomPortContextCustomizer customizer = new SpringBootTestRandomPortContextCustomizer();
private MockEnvironment environment; private MockEnvironment environment;
@ -56,7 +56,7 @@ class SpringBootTestRandomPortApplicationListenerTests {
@Test @Test
void postProcessWhenServerAndManagementPortIsZeroInTestPropertySource() { void postProcessWhenServerAndManagementPortIsZeroInTestPropertySource() {
addTestPropertySource("0", "0"); addTestPropertySource("0", "0");
this.listener.postProcessEnvironment(this.environment); this.customizer.postProcessEnvironment(this.environment);
assertThat(this.environment.getProperty("server.port")).isEqualTo("0"); assertThat(this.environment.getProperty("server.port")).isEqualTo("0");
assertThat(this.environment.getProperty("management.server.port")).isEqualTo("0"); assertThat(this.environment.getProperty("management.server.port")).isEqualTo("0");
} }
@ -67,7 +67,7 @@ class SpringBootTestRandomPortApplicationListenerTests {
Map<String, Object> source = new HashMap<>(); Map<String, Object> source = new HashMap<>();
source.put("management.server.port", "0"); source.put("management.server.port", "0");
this.propertySources.addLast(new MapPropertySource("other", source)); this.propertySources.addLast(new MapPropertySource("other", source));
this.listener.postProcessEnvironment(this.environment); this.customizer.postProcessEnvironment(this.environment);
assertThat(this.environment.getProperty("server.port")).isEqualTo("0"); assertThat(this.environment.getProperty("server.port")).isEqualTo("0");
assertThat(this.environment.getProperty("management.server.port")).isEqualTo("0"); assertThat(this.environment.getProperty("management.server.port")).isEqualTo("0");
} }
@ -77,7 +77,7 @@ class SpringBootTestRandomPortApplicationListenerTests {
addTestPropertySource("8080", "8081"); addTestPropertySource("8080", "8081");
this.environment.setProperty("server.port", "8080"); this.environment.setProperty("server.port", "8080");
this.environment.setProperty("management.server.port", "8081"); this.environment.setProperty("management.server.port", "8081");
this.listener.postProcessEnvironment(this.environment); this.customizer.postProcessEnvironment(this.environment);
assertThat(this.environment.getProperty("server.port")).isEqualTo("8080"); assertThat(this.environment.getProperty("server.port")).isEqualTo("8080");
assertThat(this.environment.getProperty("management.server.port")).isEqualTo("8081"); assertThat(this.environment.getProperty("management.server.port")).isEqualTo("8081");
} }
@ -85,7 +85,7 @@ class SpringBootTestRandomPortApplicationListenerTests {
@Test @Test
void postProcessWhenTestServerPortIsZeroAndTestManagementPortIsNotNull() { void postProcessWhenTestServerPortIsZeroAndTestManagementPortIsNotNull() {
addTestPropertySource("0", "8080"); addTestPropertySource("0", "8080");
this.listener.postProcessEnvironment(this.environment); this.customizer.postProcessEnvironment(this.environment);
assertThat(this.environment.getProperty("server.port")).isEqualTo("0"); assertThat(this.environment.getProperty("server.port")).isEqualTo("0");
assertThat(this.environment.getProperty("management.server.port")).isEqualTo("8080"); assertThat(this.environment.getProperty("management.server.port")).isEqualTo("8080");
} }
@ -93,7 +93,7 @@ class SpringBootTestRandomPortApplicationListenerTests {
@Test @Test
void postProcessWhenTestServerPortIsZeroAndManagementPortIsNull() { void postProcessWhenTestServerPortIsZeroAndManagementPortIsNull() {
addTestPropertySource("0", null); addTestPropertySource("0", null);
this.listener.postProcessEnvironment(this.environment); this.customizer.postProcessEnvironment(this.environment);
assertThat(this.environment.getProperty("server.port")).isEqualTo("0"); assertThat(this.environment.getProperty("server.port")).isEqualTo("0");
assertThat(this.environment.getProperty("management.server.port")).isNull(); assertThat(this.environment.getProperty("management.server.port")).isNull();
} }
@ -106,7 +106,7 @@ class SpringBootTestRandomPortApplicationListenerTests {
other.put("management.server.port", "8081"); other.put("management.server.port", "8081");
MapPropertySource otherSource = new MapPropertySource("other", other); MapPropertySource otherSource = new MapPropertySource("other", other);
this.propertySources.addLast(otherSource); this.propertySources.addLast(otherSource);
this.listener.postProcessEnvironment(this.environment); this.customizer.postProcessEnvironment(this.environment);
assertThat(this.environment.getProperty("server.port")).isEqualTo("0"); assertThat(this.environment.getProperty("server.port")).isEqualTo("0");
assertThat(this.environment.getProperty("management.server.port")).isEmpty(); assertThat(this.environment.getProperty("management.server.port")).isEmpty();
} }
@ -118,7 +118,7 @@ class SpringBootTestRandomPortApplicationListenerTests {
addTestPropertySource("0", null); addTestPropertySource("0", null);
this.propertySources this.propertySources
.addLast(new MapPropertySource("other", Collections.singletonMap("management.server.port", "8080"))); .addLast(new MapPropertySource("other", Collections.singletonMap("management.server.port", "8080")));
this.listener.postProcessEnvironment(this.environment); this.customizer.postProcessEnvironment(this.environment);
assertThat(this.environment.getProperty("server.port")).isEqualTo("0"); assertThat(this.environment.getProperty("server.port")).isEqualTo("0");
assertThat(this.environment.getProperty("management.server.port")).isEmpty(); assertThat(this.environment.getProperty("management.server.port")).isEmpty();
} }
@ -128,7 +128,7 @@ class SpringBootTestRandomPortApplicationListenerTests {
addTestPropertySource("0", null); addTestPropertySource("0", null);
this.propertySources this.propertySources
.addLast(new MapPropertySource("other", Collections.singletonMap("management.server.port", "8081"))); .addLast(new MapPropertySource("other", Collections.singletonMap("management.server.port", "8081")));
this.listener.postProcessEnvironment(this.environment); this.customizer.postProcessEnvironment(this.environment);
assertThat(this.environment.getProperty("server.port")).isEqualTo("0"); assertThat(this.environment.getProperty("server.port")).isEqualTo("0");
assertThat(this.environment.getProperty("management.server.port")).isEqualTo("0"); assertThat(this.environment.getProperty("management.server.port")).isEqualTo("0");
} }
@ -138,7 +138,7 @@ class SpringBootTestRandomPortApplicationListenerTests {
addTestPropertySource("0", null); addTestPropertySource("0", null);
this.propertySources this.propertySources
.addLast(new MapPropertySource("other", Collections.singletonMap("management.server.port", "-1"))); .addLast(new MapPropertySource("other", Collections.singletonMap("management.server.port", "-1")));
this.listener.postProcessEnvironment(this.environment); this.customizer.postProcessEnvironment(this.environment);
assertThat(this.environment.getProperty("server.port")).isEqualTo("0"); assertThat(this.environment.getProperty("server.port")).isEqualTo("0");
assertThat(this.environment.getProperty("management.server.port")).isEqualTo("-1"); assertThat(this.environment.getProperty("management.server.port")).isEqualTo("-1");
} }
@ -148,7 +148,7 @@ class SpringBootTestRandomPortApplicationListenerTests {
addTestPropertySource("0", null); addTestPropertySource("0", null);
this.propertySources this.propertySources
.addLast(new MapPropertySource("other", Collections.singletonMap("management.server.port", 8081))); .addLast(new MapPropertySource("other", Collections.singletonMap("management.server.port", 8081)));
this.listener.postProcessEnvironment(this.environment); this.customizer.postProcessEnvironment(this.environment);
assertThat(this.environment.getProperty("server.port")).isEqualTo("0"); assertThat(this.environment.getProperty("server.port")).isEqualTo("0");
assertThat(this.environment.getProperty("management.server.port")).isEqualTo("0"); assertThat(this.environment.getProperty("management.server.port")).isEqualTo("0");
} }
@ -162,7 +162,7 @@ class SpringBootTestRandomPortApplicationListenerTests {
testPropertySource.getSource().put("port", "9090"); testPropertySource.getSource().put("port", "9090");
this.propertySources this.propertySources
.addLast(new MapPropertySource("other", Collections.singletonMap("management.server.port", "${port}"))); .addLast(new MapPropertySource("other", Collections.singletonMap("management.server.port", "${port}")));
this.listener.postProcessEnvironment(this.environment); this.customizer.postProcessEnvironment(this.environment);
assertThat(this.environment.getProperty("server.port")).isEqualTo("0"); assertThat(this.environment.getProperty("server.port")).isEqualTo("0");
assertThat(this.environment.getProperty("management.server.port")).isEqualTo("0"); assertThat(this.environment.getProperty("management.server.port")).isEqualTo("0");
} }
@ -173,7 +173,7 @@ class SpringBootTestRandomPortApplicationListenerTests {
this.propertySources this.propertySources
.addLast(new MapPropertySource("other", Collections.singletonMap("management.server.port", "${port}"))); .addLast(new MapPropertySource("other", Collections.singletonMap("management.server.port", "${port}")));
assertThatExceptionOfType(PlaceholderResolutionException.class) assertThatExceptionOfType(PlaceholderResolutionException.class)
.isThrownBy(() -> this.listener.postProcessEnvironment(this.environment)) .isThrownBy(() -> this.customizer.postProcessEnvironment(this.environment))
.withMessage("Could not resolve placeholder 'port' in value \"${port}\""); .withMessage("Could not resolve placeholder 'port' in value \"${port}\"");
} }
@ -188,7 +188,7 @@ class SpringBootTestRandomPortApplicationListenerTests {
source.put("server.port", "${port}"); source.put("server.port", "${port}");
source.put("management.server.port", "9090"); source.put("management.server.port", "9090");
this.propertySources.addLast(new MapPropertySource("other", source)); this.propertySources.addLast(new MapPropertySource("other", source));
this.listener.postProcessEnvironment(this.environment); this.customizer.postProcessEnvironment(this.environment);
assertThat(this.environment.getProperty("server.port")).isEqualTo("0"); assertThat(this.environment.getProperty("server.port")).isEqualTo("0");
assertThat(this.environment.getProperty("management.server.port")).isEqualTo("0"); assertThat(this.environment.getProperty("management.server.port")).isEqualTo("0");
} }
@ -201,7 +201,7 @@ class SpringBootTestRandomPortApplicationListenerTests {
source.put("management.server.port", "9090"); source.put("management.server.port", "9090");
this.propertySources.addLast(new MapPropertySource("other", source)); this.propertySources.addLast(new MapPropertySource("other", source));
assertThatExceptionOfType(PlaceholderResolutionException.class) assertThatExceptionOfType(PlaceholderResolutionException.class)
.isThrownBy(() -> this.listener.postProcessEnvironment(this.environment)) .isThrownBy(() -> this.customizer.postProcessEnvironment(this.environment))
.withMessage("Could not resolve placeholder 'port' in value \"${port}\""); .withMessage("Could not resolve placeholder 'port' in value \"${port}\"");
} }

65
smoke-test/spring-boot-smoke-test-actuator/src/test/java/smoketest/actuator/ManagementRandomPortWithConfiguredPortSampleActuatorApplicationTests.java

@ -0,0 +1,65 @@
/*
* Copyright 2012-present 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
*
* https://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 smoketest.actuator;
import org.junit.jupiter.api.Test;
import org.springframework.boot.resttestclient.TestRestTemplate;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.server.LocalManagementPort;
import org.springframework.boot.test.web.server.LocalServerPort;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for separate management and main service ports when a management port
* is set.
*
* @author Stephane Nicoll
*/
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, args = "--management.server.port=1234")
class ManagementRandomPortWithConfiguredPortSampleActuatorApplicationTests {
@LocalServerPort
private int serverPort;
@LocalManagementPort
private int managementPort;
@Test
void randomPortsShouldBeDifferent() {
assertThat(this.serverPort).isPositive();
assertThat(this.managementPort).isPositive();
assertThat(this.serverPort).isNotEqualTo(this.managementPort);
}
@Test
void randomManagementPortShouldBeApplied() {
assertThat(this.managementPort).isNotEqualTo(1234);
}
@Test
void testHealth() {
ResponseEntity<String> entity = new TestRestTemplate().withBasicAuth("user", "password")
.getForEntity("http://localhost:" + this.managementPort + "/actuator/health", String.class);
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
assertThat(entity.getBody()).contains("\"status\":\"UP\"");
}
}
Loading…
Cancel
Save