Move RestTestClientBuilderCustomizer to spring-boot-test

Relocate `RestTestClientBuilderCustomizer` to `spring-boot-test`
and break the direct link to web-server by making use of
`spring.factories` and the new `BaseUrlProviders` class.

See gh-46356
This commit is contained in:
Phillip Webb
2025-10-01 21:51:20 -07:00
parent 6f909114e7
commit bba56ffc8b
125 changed files with 291 additions and 192 deletions
+2 -1
View File
@@ -55,8 +55,9 @@ dependencies {
intTestImplementation(project(":core:spring-boot-autoconfigure"))
intTestImplementation(project(":core:spring-boot-test"))
intTestImplementation(project(":module:spring-boot-restclient"))
intTestImplementation(project(":test-support:spring-boot-test-support"))
intTestImplementation(project(":module:spring-boot-restclient-test"))
intTestImplementation(project(":module:spring-boot-web-server-test"))
intTestImplementation(project(":test-support:spring-boot-test-support"))
intTestImplementation("org.apache.httpcomponents.client5:httpclient5")
intTestImplementation("net.bytebuddy:byte-buddy")
@@ -26,7 +26,7 @@ import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.boot.restclient.RestTemplateBuilder;
import org.springframework.boot.web.server.test.client.TestRestTemplate;
import org.springframework.boot.restclient.test.TestRestTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
@@ -19,7 +19,7 @@ package org.springframework.boot.devtools.tests;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.boot.web.server.test.client.TestRestTemplate;
import org.springframework.boot.restclient.test.TestRestTemplate;
import org.springframework.http.HttpStatus;
import static org.assertj.core.api.Assertions.assertThat;
+1
View File
@@ -38,6 +38,7 @@ dependencies {
testImplementation(project(":module:spring-boot-reactor-netty"))
testImplementation(project(":module:spring-boot-restclient"))
testImplementation(project(":module:spring-boot-reactor-netty"))
testImplementation(project(":module:spring-boot-restclient-test"))
testImplementation(project(":module:spring-boot-tomcat"))
testImplementation(project(":module:spring-boot-webflux-test"))
testImplementation(project(":module:spring-boot-webmvc-test"))
@@ -30,11 +30,11 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.mustache.servlet.view.MustacheView;
import org.springframework.boot.mustache.servlet.view.MustacheViewResolver;
import org.springframework.boot.restclient.test.TestRestTemplate;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.tomcat.autoconfigure.servlet.TomcatServletWebServerAutoConfiguration;
import org.springframework.boot.web.server.servlet.context.ServletWebServerApplicationContext;
import org.springframework.boot.web.server.test.client.TestRestTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
@@ -15,7 +15,9 @@
*/
plugins {
id "dev.adamko.dokkatoo-html"
id "java-library"
id "org.jetbrains.kotlin.jvm"
id "org.springframework.boot.deployed"
id "org.springframework.boot.optional-dependencies"
id "org.springframework.boot.test-slice"
@@ -24,12 +26,15 @@ plugins {
description = "Spring Boot RestClient Test"
dependencies {
api(project(":core:spring-boot"))
api(project(":core:spring-boot-test-autoconfigure"))
api(project(":module:spring-boot-restclient"))
optional(project(":core:spring-boot-autoconfigure"))
optional(project(":module:spring-boot-jackson"))
optional(project(":module:spring-boot-restclient"))
optional("org.apache.httpcomponents.client5:httpclient5")
optional("org.jetbrains.kotlin:kotlin-stdlib")
optional("org.jetbrains.kotlin:kotlin-reflect")
optional("org.junit.jupiter:junit-jupiter-api")
optional("org.springframework:spring-test")
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.boot.web.server.test.client;
package org.springframework.boot.restclient.test;
import java.net.URI;
import java.security.KeyManagementException;
@@ -1006,11 +1006,10 @@ public class TestRestTemplate {
}
private URI applyRootUriIfNecessary(URI uri) {
UriTemplateHandler uriTemplateHandler = this.restTemplate.getUriTemplateHandler();
if ((uriTemplateHandler instanceof RootUriTemplateHandler rootHandler) && uri.toString().startsWith("/")) {
return URI.create(rootHandler.getRootUri() + uri);
if (!uri.toString().startsWith("/")) {
return uri;
}
return uri;
return URI.create(this.restTemplate.getUriTemplateHandler().expand("/") + uri.toString().substring(1));
}
private URI resolveUri(RequestEntity<?> entity) {
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.boot.web.server.test.client;
package org.springframework.boot.restclient.test;
import org.jspecify.annotations.Nullable;
@@ -32,9 +32,11 @@ import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.boot.restclient.RestTemplateBuilder;
import org.springframework.boot.restclient.test.TestRestTemplate.HttpClientOption;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.AbstractConfigurableWebServerFactory;
import org.springframework.boot.web.server.test.client.TestRestTemplate.HttpClientOption;
import org.springframework.boot.test.http.server.BaseUrl;
import org.springframework.boot.test.http.server.BaseUrlProviders;
import org.springframework.boot.test.web.servlet.client.BaseUrlUriBuilderFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
@@ -120,7 +122,6 @@ class TestRestTemplateContextCustomizer implements ContextCustomizer {
registry.registerBeanDefinition(TestRestTemplate.class.getName(),
new RootBeanDefinition(TestRestTemplateFactory.class));
}
}
@Override
@@ -144,24 +145,10 @@ class TestRestTemplateContextCustomizer implements ContextCustomizer {
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
RestTemplateBuilder builder = getRestTemplateBuilder(applicationContext);
boolean sslEnabled = isSslEnabled(applicationContext);
TestRestTemplate template = new TestRestTemplate(builder, null, null,
sslEnabled ? SSL_OPTIONS : DEFAULT_OPTIONS);
LocalHostUriTemplateHandler handler = new LocalHostUriTemplateHandler(applicationContext.getEnvironment(),
sslEnabled ? "https" : "http");
template.setUriTemplateHandler(handler);
this.template = template;
}
private boolean isSslEnabled(ApplicationContext context) {
try {
AbstractConfigurableWebServerFactory webServerFactory = context
.getBean(AbstractConfigurableWebServerFactory.class);
return webServerFactory.getSsl() != null && webServerFactory.getSsl().isEnabled();
}
catch (NoSuchBeanDefinitionException ex) {
return false;
}
BaseUrl baseUrl = new BaseUrlProviders(applicationContext).getBaseUrlOrDefault();
boolean sslEnabled = baseUrl != null && baseUrl.isHttps();
this.template = new TestRestTemplate(builder, null, null, sslEnabled ? SSL_OPTIONS : DEFAULT_OPTIONS);
this.template.setUriTemplateHandler(BaseUrlUriBuilderFactory.get(baseUrl));
}
private RestTemplateBuilder getRestTemplateBuilder(ApplicationContext applicationContext) {
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.boot.web.server.test.client;
package org.springframework.boot.restclient.test;
import java.util.List;
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.boot.web.server.test.client
package org.springframework.boot.restclient.test
import org.springframework.core.ParameterizedTypeReference
import org.springframework.http.HttpEntity
@@ -1,3 +1,7 @@
# Spring Test Execution Listeners
org.springframework.test.context.TestExecutionListener=\
org.springframework.boot.restclient.test.autoconfigure.MockRestServiceServerResetTestExecutionListener
# Spring Test Context Customizer Factories
org.springframework.test.context.ContextCustomizerFactory=\
org.springframework.boot.restclient.test.TestRestTemplateContextCustomizerFactory
@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.boot.web.server.test.client;
package org.springframework.boot.restclient.test;
import java.io.IOException;
import java.lang.reflect.Method;
@@ -36,7 +36,9 @@ import org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder;
import org.springframework.boot.http.client.ClientHttpRequestFactorySettings;
import org.springframework.boot.http.client.HttpRedirects;
import org.springframework.boot.restclient.RestTemplateBuilder;
import org.springframework.boot.web.server.test.client.TestRestTemplate.HttpClientOption;
import org.springframework.boot.restclient.test.TestRestTemplate.HttpClientOption;
import org.springframework.boot.test.http.server.BaseUrl;
import org.springframework.boot.test.web.servlet.client.BaseUrlUriBuilderFactory;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
@@ -48,7 +50,6 @@ import org.springframework.http.client.ClientHttpRequestFactory;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.http.client.JdkClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.mock.http.client.MockClientHttpRequest;
import org.springframework.mock.http.client.MockClientHttpResponse;
import org.springframework.test.util.ReflectionTestUtils;
@@ -118,16 +119,6 @@ class TestRestTemplateTests {
assertThat(new TestRestTemplate(delegate).getRootUri()).isEqualTo(rootUri);
}
@Test
void getRootUriRootUriSetViaLocalHostUriTemplateHandler() {
String rootUri = "https://example.com";
TestRestTemplate template = new TestRestTemplate();
LocalHostUriTemplateHandler templateHandler = mock(LocalHostUriTemplateHandler.class);
given(templateHandler.getRootUri()).willReturn(rootUri);
template.setUriTemplateHandler(templateHandler);
assertThat(template.getRootUri()).isEqualTo(rootUri);
}
@Test
void getRootUriRootUriNotSet() {
assertThat(new TestRestTemplate().getRootUri()).isEmpty();
@@ -348,8 +339,7 @@ class TestRestTemplateTests {
URI absoluteUri = URI.create("http://localhost:8080/a/b/c.txt");
given(requestFactory.createRequest(eq(absoluteUri), eq(HttpMethod.GET))).willReturn(request);
template.getRestTemplate().setRequestFactory(requestFactory);
LocalHostUriTemplateHandler uriTemplateHandler = new LocalHostUriTemplateHandler(new MockEnvironment());
template.setUriTemplateHandler(uriTemplateHandler);
template.setUriTemplateHandler(BaseUrlUriBuilderFactory.get(BaseUrl.of("http://localhost:8080")));
template.exchange(entity, String.class);
then(requestFactory).should().createRequest(eq(absoluteUri), eq(HttpMethod.GET));
}
@@ -464,8 +454,7 @@ class TestRestTemplateTests {
given(requestFactory.createRequest(eq(absoluteUri), any(HttpMethod.class))).willReturn(request);
TestRestTemplate template = new TestRestTemplate();
template.getRestTemplate().setRequestFactory(requestFactory);
LocalHostUriTemplateHandler uriTemplateHandler = new LocalHostUriTemplateHandler(new MockEnvironment());
template.setUriTemplateHandler(uriTemplateHandler);
template.setUriTemplateHandler(BaseUrlUriBuilderFactory.get(BaseUrl.of("http://localhost:8080")));
callback.doWithTestRestTemplate(template, URI.create("/a/b/c.txt?param=%7Bsomething%7D"));
then(requestFactory).should().createRequest(eq(absoluteUri), any(HttpMethod.class));
}
@@ -1,58 +0,0 @@
/*
* 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 org.springframework.boot.restclient.test.scan;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
/**
* A simple factory bean with no generics. Used to test early initialization doesn't
* occur.
*
* @author Madhura Bhave
*/
@Component
@SuppressWarnings("rawtypes")
public class SimpleFactoryBean implements FactoryBean {
private static boolean isInitializedEarly = false;
public SimpleFactoryBean() {
isInitializedEarly = true;
throw new RuntimeException();
}
@Autowired
public SimpleFactoryBean(ApplicationContext context) {
if (isInitializedEarly) {
throw new RuntimeException();
}
}
@Override
public Object getObject() {
return new Object();
}
@Override
public Class<?> getObjectType() {
return Object.class;
}
}
+1
View File
@@ -35,6 +35,7 @@ dependencies {
optional(project(":module:spring-boot-actuator-autoconfigure"))
optional(project(":module:spring-boot-h2console"))
optional(project(":module:spring-boot-reactor"))
optional(project(":module:spring-boot-restclient-test"))
optional(project(":module:spring-boot-rsocket"))
optional(project(":module:spring-boot-webflux"))
optional(project(":module:spring-boot-webmvc"))
@@ -31,6 +31,7 @@ import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.http.converter.autoconfigure.HttpMessageConvertersAutoConfiguration;
import org.springframework.boot.jackson.autoconfigure.JacksonAutoConfiguration;
import org.springframework.boot.restclient.test.TestRestTemplate;
import org.springframework.boot.test.system.CapturedOutput;
import org.springframework.boot.test.system.OutputCaptureExtension;
import org.springframework.boot.test.util.TestPropertyValues;
@@ -38,7 +39,6 @@ import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
import org.springframework.boot.testsupport.web.servlet.DirtiesUrlFactories;
import org.springframework.boot.tomcat.servlet.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.boot.web.server.test.client.TestRestTemplate;
import org.springframework.boot.webmvc.autoconfigure.DispatcherServletAutoConfiguration;
import org.springframework.boot.webmvc.autoconfigure.WebMvcAutoConfiguration;
import org.springframework.context.annotation.Bean;
@@ -17,7 +17,6 @@
plugins {
id "dev.adamko.dokkatoo-html"
id "java-library"
id "org.jetbrains.kotlin.jvm"
id "org.springframework.boot.deployed"
id "org.springframework.boot.optional-dependencies"
id "org.springframework.boot.test-auto-configuration"
@@ -35,7 +34,6 @@ dependencies {
optional(project(":module:spring-boot-web-server"))
optional(project(":module:spring-boot-webclient"))
optional("jakarta.servlet:jakarta.servlet-api")
optional("org.apache.httpcomponents.client5:httpclient5")
optional("org.htmlunit:htmlunit")
optional("org.jetbrains.kotlin:kotlin-reflect")
optional("org.jetbrains.kotlin:kotlin-stdlib")
@@ -1,38 +0,0 @@
/*
* 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 org.springframework.boot.web.server.test.client;
import org.springframework.test.web.servlet.client.RestTestClient;
/**
* A customizer that can be implemented by beans wishing to customize the
* {@link RestTestClient.Builder} to fine-tine its auto-configuration before a
* {@link RestTestClient} is created.
*
* @author Stephane Nicoll
* @since 4.0.0
*/
@FunctionalInterface
public interface RestTestClientBuilderCustomizer {
/**
* Customize the given {@link RestTestClient.Builder Builder}.
* @param builder the builder
*/
void customize(RestTestClient.Builder<?> builder);
}
@@ -1,194 +0,0 @@
/*
* 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 org.springframework.boot.web.server.test.client;
import org.jspecify.annotations.Nullable;
import org.springframework.aot.AotDetector;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.boot.restclient.RootUriBuilderFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.web.server.reactive.AbstractReactiveWebServerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.core.Ordered;
import org.springframework.test.context.ContextCustomizer;
import org.springframework.test.context.MergedContextConfiguration;
import org.springframework.test.context.TestContextAnnotationUtils;
import org.springframework.test.web.servlet.client.RestTestClient;
import org.springframework.util.Assert;
/**
* {@link ContextCustomizer} for {@link RestTestClient}.
*
* @author Stephane Nicoll
*/
class RestTestClientContextCustomizer implements ContextCustomizer {
@Override
public void customizeContext(ConfigurableApplicationContext context, MergedContextConfiguration mergedConfig) {
if (AotDetector.useGeneratedArtifacts()) {
return;
}
SpringBootTest springBootTest = TestContextAnnotationUtils.findMergedAnnotation(mergedConfig.getTestClass(),
SpringBootTest.class);
Assert.state(springBootTest != null, "'springBootTest' must not be null");
if (springBootTest.webEnvironment().isEmbedded()) {
registerRestTestClient(context);
}
}
private void registerRestTestClient(ConfigurableApplicationContext context) {
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
if (beanFactory instanceof BeanDefinitionRegistry registry) {
registerRestTestClient(registry);
}
}
private void registerRestTestClient(BeanDefinitionRegistry registry) {
RootBeanDefinition definition = new RootBeanDefinition(RestTestClientRegistrar.class);
definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(RestTestClientRegistrar.class.getName(), definition);
}
@Override
public boolean equals(@Nullable Object obj) {
return (obj != null) && (obj.getClass() == getClass());
}
@Override
public int hashCode() {
return getClass().hashCode();
}
/**
* {@link BeanDefinitionRegistryPostProcessor} that runs after the
* {@link ConfigurationClassPostProcessor} and add a {@link RestTestClientFactory}
* bean definition when a {@link RestTestClient} hasn't already been registered.
*/
static class RestTestClientRegistrar implements BeanDefinitionRegistryPostProcessor, Ordered, BeanFactoryAware {
@SuppressWarnings("NullAway.Init")
private BeanFactory beanFactory;
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
@Override
public int getOrder() {
return Ordered.LOWEST_PRECEDENCE;
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
if (AotDetector.useGeneratedArtifacts()) {
return;
}
if (BeanFactoryUtils.beanNamesForTypeIncludingAncestors((ListableBeanFactory) this.beanFactory,
RestTestClient.class, false, false).length == 0) {
registry.registerBeanDefinition(RestTestClient.class.getName(),
new RootBeanDefinition(RestTestClientFactory.class));
}
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
/**
* {@link FactoryBean} used to create and configure a {@link RestTestClient}.
*/
public static class RestTestClientFactory implements FactoryBean<RestTestClient>, ApplicationContextAware {
@SuppressWarnings("NullAway.Init")
private ApplicationContext applicationContext;
private @Nullable RestTestClient object;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
@Override
public boolean isSingleton() {
return true;
}
@Override
public Class<?> getObjectType() {
return RestTestClient.class;
}
@Override
public RestTestClient getObject() {
if (this.object == null) {
this.object = createRestTestClient();
}
return this.object;
}
private RestTestClient createRestTestClient() {
boolean sslEnabled = isSslEnabled(this.applicationContext);
LocalHostUriTemplateHandler handler = new LocalHostUriTemplateHandler(
this.applicationContext.getEnvironment(), sslEnabled ? "https" : "http");
RestTestClient.Builder<?> builder = RestTestClient.bindToServer();
customizeRestTestClientBuilder(builder, this.applicationContext);
return builder.uriBuilderFactory(new RootUriBuilderFactory(handler.getRootUri(), handler)).build();
}
private boolean isSslEnabled(ApplicationContext context) {
try {
AbstractReactiveWebServerFactory webServerFactory = context
.getBean(AbstractReactiveWebServerFactory.class);
return webServerFactory.getSsl() != null && webServerFactory.getSsl().isEnabled();
}
catch (NoSuchBeanDefinitionException ex) {
return false;
}
}
private void customizeRestTestClientBuilder(RestTestClient.Builder<?> clientBuilder,
ApplicationContext context) {
for (RestTestClientBuilderCustomizer customizer : context
.getBeansOfType(RestTestClientBuilderCustomizer.class)
.values()) {
customizer.customize(clientBuilder);
}
}
}
}
@@ -1,52 +0,0 @@
/*
* 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 org.springframework.boot.web.server.test.client;
import java.util.List;
import org.jspecify.annotations.Nullable;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ContextConfigurationAttributes;
import org.springframework.test.context.ContextCustomizer;
import org.springframework.test.context.ContextCustomizerFactory;
import org.springframework.test.context.TestContextAnnotationUtils;
import org.springframework.util.ClassUtils;
/**
* {@link ContextCustomizerFactory} for {@code RestTestClient}.
*
* @author Stephane Nicoll
*/
class RestTestClientContextCustomizerFactory implements ContextCustomizerFactory {
private static final boolean restClientPresent;
static {
ClassLoader loader = RestTestClientContextCustomizerFactory.class.getClassLoader();
restClientPresent = ClassUtils.isPresent("org.springframework.web.client.RestClient", loader);
}
@Override
public @Nullable ContextCustomizer createContextCustomizer(Class<?> testClass,
List<ContextConfigurationAttributes> configAttributes) {
SpringBootTest springBootTest = TestContextAnnotationUtils.findMergedAnnotation(testClass,
SpringBootTest.class);
return (springBootTest != null && restClientPresent) ? new RestTestClientContextCustomizer() : null;
}
}
@@ -4,6 +4,4 @@ org.springframework.boot.web.server.test.SpringBootTestRandomPortEnvironmentPost
# Spring Test Context Customizer Factories
org.springframework.test.context.ContextCustomizerFactory=\
org.springframework.boot.web.server.test.client.RestTestClientContextCustomizerFactory,\
org.springframework.boot.web.server.test.client.TestRestTemplateContextCustomizerFactory,\
org.springframework.boot.web.server.test.reactor.netty.DisableReactorResourceFactoryGlobalResourcesContextCustomizerFactory
@@ -1,129 +0,0 @@
/*
* 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 org.springframework.boot.web.server.test;
import java.time.Duration;
import org.junit.jupiter.api.Test;
import reactor.core.publisher.Mono;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.tomcat.reactive.TomcatReactiveWebServerFactory;
import org.springframework.boot.web.context.reactive.ReactiveWebApplicationContext;
import org.springframework.boot.web.server.reactive.ReactiveWebServerFactory;
import org.springframework.boot.web.server.test.client.TestRestTemplate;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Base class for {@link SpringBootTest @SpringBootTest} tests configured to start an
* embedded reactive container.
*
* @author Stephane Nicoll
*/
abstract class AbstractSpringBootTestEmbeddedReactiveWebEnvironmentTests {
@LocalServerPort
private int port = 0;
@Value("${value}")
private int value = 0;
@Autowired
private ReactiveWebApplicationContext context;
@Autowired
private WebTestClient webClient;
@Autowired
private TestRestTemplate restTemplate;
ReactiveWebApplicationContext getContext() {
return this.context;
}
@Test
void runAndTestHttpEndpoint() {
assertThat(this.port).isNotEqualTo(8080).isNotZero();
WebTestClient.bindToServer()
.baseUrl("http://localhost:" + this.port)
.responseTimeout(Duration.ofMinutes(5))
.build()
.get()
.uri("/")
.exchange()
.expectBody(String.class)
.isEqualTo("Hello World");
}
@Test
void injectWebTestClient() {
this.webClient.get().uri("/").exchange().expectBody(String.class).isEqualTo("Hello World");
}
@Test
void injectTestRestTemplate() {
String body = this.restTemplate.getForObject("/", String.class);
assertThat(body).isEqualTo("Hello World");
}
@Test
void annotationAttributesOverridePropertiesFile() {
assertThat(this.value).isEqualTo(123);
}
@Configuration(proxyBeanMethods = false)
static class AbstractConfig {
@Value("${server.port:8080}")
private int port = 8080;
@Bean
HttpHandler httpHandler(ApplicationContext applicationContext) {
return WebHttpHandlerBuilder.applicationContext(applicationContext).build();
}
@Bean
ReactiveWebServerFactory webServerFactory() {
TomcatReactiveWebServerFactory factory = new TomcatReactiveWebServerFactory();
factory.setPort(this.port);
return factory;
}
@Bean
static PropertySourcesPlaceholderConfigurer propertyPlaceholder() {
return new PropertySourcesPlaceholderConfigurer();
}
@RequestMapping("/")
Mono<String> home() {
return Mono.just("Hello World");
}
}
}
@@ -1,124 +0,0 @@
/*
* 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 org.springframework.boot.web.server.test;
import jakarta.servlet.ServletContext;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.tomcat.servlet.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.servlet.ServletWebServerFactory;
import org.springframework.boot.web.server.test.client.TestRestTemplate;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.DispatcherServlet;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Base class for {@link SpringBootTest @SpringBootTest} tests configured to start an
* embedded web server.
*
* @author Phillip Webb
* @author Andy Wilkinson
*/
abstract class AbstractSpringBootTestWebServerWebEnvironmentTests {
@LocalServerPort
private int port = 0;
@Value("${value}")
private int value = 0;
@Autowired
private WebApplicationContext context;
@Autowired
private ServletContext servletContext;
@Autowired
private TestRestTemplate restTemplate;
WebApplicationContext getContext() {
return this.context;
}
TestRestTemplate getRestTemplate() {
return this.restTemplate;
}
@Test
void runAndTestHttpEndpoint() {
assertThat(this.port).isNotEqualTo(8080).isNotZero();
String body = new RestTemplate().getForObject("http://localhost:" + this.port + "/", String.class);
assertThat(body).isEqualTo("Hello World");
}
@Test
void injectTestRestTemplate() {
String body = this.restTemplate.getForObject("/", String.class);
assertThat(body).isEqualTo("Hello World");
}
@Test
void annotationAttributesOverridePropertiesFile() {
assertThat(this.value).isEqualTo(123);
}
@Test
void validateWebApplicationContextIsSet() {
assertThat(this.context).isSameAs(WebApplicationContextUtils.getWebApplicationContext(this.servletContext));
}
@Configuration(proxyBeanMethods = false)
static class AbstractConfig {
@Value("${server.port:8080}")
private int port = 8080;
@Bean
DispatcherServlet dispatcherServlet() {
return new DispatcherServlet();
}
@Bean
ServletWebServerFactory webServerFactory() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
factory.setPort(this.port);
return factory;
}
@Bean
static PropertySourcesPlaceholderConfigurer propertyPlaceholder() {
return new PropertySourcesPlaceholderConfigurer();
}
@RequestMapping("/")
String home() {
return "Hello World";
}
}
}
@@ -1,54 +0,0 @@
/*
* 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 org.springframework.boot.web.server.test;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link LocalManagementPort @LocalManagementPort}.
*
* @author Andy Wilkinson
*/
@ExtendWith(SpringExtension.class)
@TestPropertySource(properties = "local.management.port=8181")
class LocalManagementPortTests {
@Value("${local.management.port}")
private String fromValue;
@LocalManagementPort
private String fromAnnotation;
@Test
void testLocalManagementPortAnnotation() {
assertThat(this.fromAnnotation).isNotNull().isEqualTo(this.fromValue);
}
@Configuration(proxyBeanMethods = false)
static class Config {
}
}
@@ -1,55 +0,0 @@
/*
* 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 org.springframework.boot.web.server.test;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link LocalServerPort @LocalServerPort}.
*
* @author Anand Shah
* @author Phillip Webb
*/
@ExtendWith(SpringExtension.class)
@TestPropertySource(properties = "local.server.port=8181")
class LocalServerPortTests {
@Value("${local.server.port}")
private String fromValue;
@LocalServerPort
private String fromAnnotation;
@Test
void testLocalServerPortAnnotation() {
assertThat(this.fromAnnotation).isNotNull().isEqualTo(this.fromValue);
}
@Configuration(proxyBeanMethods = false)
static class Config {
}
}
@@ -1,214 +0,0 @@
/*
* 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 org.springframework.boot.web.server.test;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.test.context.support.TestPropertySourceUtils;
import org.springframework.util.PlaceholderResolutionException;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
/**
* Tests for {@link SpringBootTestRandomPortEnvironmentPostProcessor}.
*
* @author Madhura Bhave
* @author Andy Wilkinson
*/
class SpringBootTestRandomPortEnvironmentPostProcessorTests {
private final SpringBootTestRandomPortEnvironmentPostProcessor postProcessor = new SpringBootTestRandomPortEnvironmentPostProcessor();
private MockEnvironment environment;
private MutablePropertySources propertySources;
@BeforeEach
void setup() {
this.environment = new MockEnvironment();
this.propertySources = this.environment.getPropertySources();
}
@Test
void postProcessWhenServerAndManagementPortIsZeroInTestPropertySource() {
addTestPropertySource("0", "0");
this.postProcessor.postProcessEnvironment(this.environment, null);
assertThat(this.environment.getProperty("server.port")).isEqualTo("0");
assertThat(this.environment.getProperty("management.server.port")).isEqualTo("0");
}
@Test
void postProcessWhenServerPortAndManagementPortIsZeroInDifferentPropertySources() {
addTestPropertySource("0", null);
Map<String, Object> source = new HashMap<>();
source.put("management.server.port", "0");
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
void postProcessWhenTestServerAndTestManagementPortAreNonZero() {
addTestPropertySource("8080", "8081");
this.environment.setProperty("server.port", "8080");
this.environment.setProperty("management.server.port", "8081");
this.postProcessor.postProcessEnvironment(this.environment, null);
assertThat(this.environment.getProperty("server.port")).isEqualTo("8080");
assertThat(this.environment.getProperty("management.server.port")).isEqualTo("8081");
}
@Test
void postProcessWhenTestServerPortIsZeroAndTestManagementPortIsNotNull() {
addTestPropertySource("0", "8080");
this.postProcessor.postProcessEnvironment(this.environment, null);
assertThat(this.environment.getProperty("server.port")).isEqualTo("0");
assertThat(this.environment.getProperty("management.server.port")).isEqualTo("8080");
}
@Test
void postProcessWhenTestServerPortIsZeroAndManagementPortIsNull() {
addTestPropertySource("0", null);
this.postProcessor.postProcessEnvironment(this.environment, null);
assertThat(this.environment.getProperty("server.port")).isEqualTo("0");
assertThat(this.environment.getProperty("management.server.port")).isNull();
}
@Test
void postProcessWhenTestServerPortIsZeroAndManagementPortIsNotNullAndSameInProduction() {
addTestPropertySource("0", null);
Map<String, Object> other = new HashMap<>();
other.put("server.port", "8081");
other.put("management.server.port", "8081");
MapPropertySource otherSource = new MapPropertySource("other", other);
this.propertySources.addLast(otherSource);
this.postProcessor.postProcessEnvironment(this.environment, null);
assertThat(this.environment.getProperty("server.port")).isEqualTo("0");
assertThat(this.environment.getProperty("management.server.port")).isEmpty();
}
@Test
void postProcessWhenTestServerPortIsZeroAndManagementPortIsNotNullAndDefaultSameInProduction() {
// mgmt port is 8080 which means it's on the same port as main server since that
// is null in app properties
addTestPropertySource("0", null);
this.propertySources
.addLast(new MapPropertySource("other", Collections.singletonMap("management.server.port", "8080")));
this.postProcessor.postProcessEnvironment(this.environment, null);
assertThat(this.environment.getProperty("server.port")).isEqualTo("0");
assertThat(this.environment.getProperty("management.server.port")).isEmpty();
}
@Test
void postProcessWhenTestServerPortIsZeroAndManagementPortIsNotNullAndDifferentInProduction() {
addTestPropertySource("0", null);
this.propertySources
.addLast(new MapPropertySource("other", Collections.singletonMap("management.server.port", "8081")));
this.postProcessor.postProcessEnvironment(this.environment, null);
assertThat(this.environment.getProperty("server.port")).isEqualTo("0");
assertThat(this.environment.getProperty("management.server.port")).isEqualTo("0");
}
@Test
void postProcessWhenTestServerPortIsZeroAndManagementPortMinusOne() {
addTestPropertySource("0", null);
this.propertySources
.addLast(new MapPropertySource("other", Collections.singletonMap("management.server.port", "-1")));
this.postProcessor.postProcessEnvironment(this.environment, null);
assertThat(this.environment.getProperty("server.port")).isEqualTo("0");
assertThat(this.environment.getProperty("management.server.port")).isEqualTo("-1");
}
@Test
void postProcessWhenTestServerPortIsZeroAndManagementPortIsAnInteger() {
addTestPropertySource("0", null);
this.propertySources
.addLast(new MapPropertySource("other", Collections.singletonMap("management.server.port", 8081)));
this.postProcessor.postProcessEnvironment(this.environment, null);
assertThat(this.environment.getProperty("server.port")).isEqualTo("0");
assertThat(this.environment.getProperty("management.server.port")).isEqualTo("0");
}
@Test
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
void postProcessWhenManagementServerPortPlaceholderAbsentShouldFail() {
addTestPropertySource("0", null);
this.propertySources
.addLast(new MapPropertySource("other", Collections.singletonMap("management.server.port", "${port}")));
assertThatExceptionOfType(PlaceholderResolutionException.class)
.isThrownBy(() -> this.postProcessor.postProcessEnvironment(this.environment, null))
.withMessage("Could not resolve placeholder 'port' in value \"${port}\"");
}
@Test
void postProcessWhenServerPortPlaceholderPresentShouldResolvePlaceholder() {
addTestPropertySource("0", null);
MapPropertySource testPropertySource = (MapPropertySource) this.propertySources
.get(TestPropertySourceUtils.INLINED_PROPERTIES_PROPERTY_SOURCE_NAME);
testPropertySource.getSource().put("port", "8080");
Map<String, Object> 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
void postProcessWhenServerPortPlaceholderAbsentShouldFail() {
addTestPropertySource("0", null);
Map<String, Object> source = new HashMap<>();
source.put("server.port", "${port}");
source.put("management.server.port", "9090");
this.propertySources.addLast(new MapPropertySource("other", source));
assertThatExceptionOfType(PlaceholderResolutionException.class)
.isThrownBy(() -> this.postProcessor.postProcessEnvironment(this.environment, null))
.withMessage("Could not resolve placeholder 'port' in value \"${port}\"");
}
private void addTestPropertySource(String serverPort, String managementPort) {
Map<String, Object> source = new HashMap<>();
source.put("server.port", serverPort);
source.put("management.server.port", managementPort);
MapPropertySource inlineTestSource = new MapPropertySource(
TestPropertySourceUtils.INLINED_PROPERTIES_PROPERTY_SOURCE_NAME, source);
this.propertySources.addFirst(inlineTestSource);
}
}
@@ -1,45 +0,0 @@
/*
* 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 org.springframework.boot.web.server.test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.config.EnableWebFlux;
/**
* Tests for {@link SpringBootTest @SpringBootTest} in a reactive environment configured
* with {@link WebEnvironment#DEFINED_PORT}.
*
* @author Stephane Nicoll
*/
@DirtiesContext
@SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT,
properties = { "spring.main.web-application-type=reactive", "server.port=0", "value=123" })
public class SpringBootTestReactiveWebEnvironmentDefinedPortTests
extends AbstractSpringBootTestEmbeddedReactiveWebEnvironmentTests {
@Configuration(proxyBeanMethods = false)
@EnableWebFlux
@RestController
static class Config extends AbstractConfig {
}
}
@@ -1,45 +0,0 @@
/*
* 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 org.springframework.boot.web.server.test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.config.EnableWebFlux;
/**
* Tests for {@link SpringBootTest @SpringBootTest} in a reactive environment configured
* with {@link WebEnvironment#RANDOM_PORT}.
*
* @author Stephane Nicoll
*/
@DirtiesContext
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT,
properties = { "spring.main.webApplicationType=reactive", "value=123" })
public class SpringBootTestReactiveWebEnvironmentRandomPortTests
extends AbstractSpringBootTestEmbeddedReactiveWebEnvironmentTests {
@Configuration(proxyBeanMethods = false)
@EnableWebFlux
@RestController
static class Config extends AbstractConfig {
}
}
@@ -1,61 +0,0 @@
/*
* 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 org.springframework.boot.web.server.test;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.config.EnableWebFlux;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link SpringBootTest @SpringBootTest} in a reactive environment configured
* with a user-defined {@link RestTemplate} that is named {@code testRestTemplate}.
*
* @author Madhura Bhave
*/
@DirtiesContext
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT,
properties = { "spring.main.web-application-type=reactive", "value=123" })
class SpringBootTestReactiveWebEnvironmentUserDefinedTestRestTemplateTests
extends AbstractSpringBootTestEmbeddedReactiveWebEnvironmentTests {
@Test
void restTemplateIsUserDefined() {
assertThat(getContext().getBean("testRestTemplate")).isInstanceOf(RestTemplate.class);
}
@Configuration(proxyBeanMethods = false)
@EnableWebFlux
@RestController
static class Config extends AbstractConfig {
@Bean
RestTemplate testRestTemplate() {
return new RestTemplate();
}
}
}
@@ -1,62 +0,0 @@
/*
* 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 org.springframework.boot.web.server.test;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link SpringBootTest @SpringBootTest} configured with a user-defined
* {@link RestTemplate} that is named {@code testRestTemplate}.
*
* @author Phillip Webb
* @author Andy Wilkinson
*/
@DirtiesContext
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = { "value=123" })
class SpringBootTestUserDefinedTestRestTemplateTests extends AbstractSpringBootTestWebServerWebEnvironmentTests {
@Test
void restTemplateIsUserDefined() {
assertThat(getContext().getBean("testRestTemplate")).isInstanceOf(RestTemplate.class);
}
// gh-7711
@Configuration(proxyBeanMethods = false)
@EnableWebMvc
@RestController
static class Config extends AbstractConfig {
@Bean
RestTemplate testRestTemplate() {
return new RestTemplate();
}
}
}
@@ -1,73 +0,0 @@
/*
* 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 org.springframework.boot.web.server.test;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.web.server.test.AbstractSpringBootTestWebServerWebEnvironmentTests.AbstractConfig;
import org.springframework.boot.web.server.test.SpringBootTestWebEnvironmentContextHierarchyTests.ChildConfiguration;
import org.springframework.boot.web.server.test.SpringBootTestWebEnvironmentContextHierarchyTests.ParentConfiguration;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.ContextHierarchy;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link SpringBootTest @SpringBootTest} configured with
* {@link WebEnvironment#DEFINED_PORT}.
*
* @author Phillip Webb
* @author Andy Wilkinson
*/
@DirtiesContext
@SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT, properties = { "server.port=0", "value=123" })
@ContextHierarchy({ @ContextConfiguration(classes = ParentConfiguration.class),
@ContextConfiguration(classes = ChildConfiguration.class) })
class SpringBootTestWebEnvironmentContextHierarchyTests {
@Autowired
private ApplicationContext context;
@Test
void testShouldOnlyStartSingleServer() {
ApplicationContext parent = this.context.getParent();
assertThat(this.context).isInstanceOf(WebApplicationContext.class);
assertThat(parent).isNotInstanceOf(WebApplicationContext.class);
}
@Configuration(proxyBeanMethods = false)
static class ParentConfiguration extends AbstractConfig {
}
@Configuration(proxyBeanMethods = false)
@EnableWebMvc
@RestController
static class ChildConfiguration extends AbstractConfig {
}
}
@@ -1,44 +0,0 @@
/*
* 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 org.springframework.boot.web.server.test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
/**
* Tests for {@link SpringBootTest @SpringBootTest} configured with
* {@link WebEnvironment#DEFINED_PORT}.
*
* @author Phillip Webb
* @author Andy Wilkinson
*/
@DirtiesContext
@SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT, properties = { "server.port=0", "value=123" })
class SpringBootTestWebEnvironmentDefinedPortTests extends AbstractSpringBootTestWebServerWebEnvironmentTests {
@Configuration(proxyBeanMethods = false)
@EnableWebMvc
@RestController
static class Config extends AbstractConfig {
}
}
@@ -1,57 +0,0 @@
/*
* 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 org.springframework.boot.web.server.test;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.web.server.test.AbstractSpringBootTestWebServerWebEnvironmentTests.AbstractConfig;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Test for {@link SpringBootTest @SpringBootTest} with a custom inline server.port in an
* embedded web environment.
*
* @author Stephane Nicoll
*/
@DirtiesContext
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = { "server.port=12345" })
class SpringBootTestWebEnvironmentRandomPortCustomPortTests {
@Autowired
private Environment environment;
@Test
void validatePortIsNotOverwritten() {
String port = this.environment.getProperty("server.port");
assertThat(port).isEqualTo("0");
}
@Configuration(proxyBeanMethods = false)
@EnableWebMvc
static class Config extends AbstractConfig {
}
}
@@ -1,66 +0,0 @@
/*
* 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 org.springframework.boot.web.server.test;
import org.junit.jupiter.api.Test;
import org.springframework.boot.restclient.RestTemplateBuilder;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link SpringBootTest @SpringBootTest} configured with
* {@link WebEnvironment#RANDOM_PORT}.
*
* @author Phillip Webb
* @author Andy Wilkinson
*/
@DirtiesContext
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, properties = { "value=123" })
class SpringBootTestWebEnvironmentRandomPortTests extends AbstractSpringBootTestWebServerWebEnvironmentTests {
@Test
void testRestTemplateShouldUseBuilder() {
assertThat(getRestTemplate().getRestTemplate().getMessageConverters())
.hasAtLeastOneElementOfType(MyConverter.class);
}
@Configuration(proxyBeanMethods = false)
@EnableWebMvc
@RestController
static class Config extends AbstractConfig {
@Bean
RestTemplateBuilder restTemplateBuilder() {
return new RestTemplateBuilder().additionalMessageConverters(new MyConverter());
}
}
static class MyConverter extends StringHttpMessageConverter {
}
}
@@ -1,105 +0,0 @@
/*
* 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 org.springframework.boot.web.server.test.client;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.springframework.mock.env.MockEnvironment;
import org.springframework.web.util.UriTemplateHandler;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link LocalHostUriTemplateHandler}.
*
* @author Phillip Webb
* @author Andy Wilkinson
* @author Eddú Meléndez
*/
class LocalHostUriTemplateHandlerTests {
@Test
void createWhenEnvironmentIsNullShouldThrowException() {
assertThatIllegalArgumentException().isThrownBy(() -> new LocalHostUriTemplateHandler(null))
.withMessageContaining("'environment' must not be null");
}
@Test
void createWhenSchemeIsNullShouldThrowException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new LocalHostUriTemplateHandler(new MockEnvironment(), null))
.withMessageContaining("'scheme' must not be null");
}
@Test
void createWhenHandlerIsNullShouldThrowException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> new LocalHostUriTemplateHandler(new MockEnvironment(), "http", null))
.withMessageContaining("'handler' must not be null");
}
@Test
void getRootUriShouldUseLocalServerPort() {
MockEnvironment environment = new MockEnvironment();
environment.setProperty("local.server.port", "1234");
LocalHostUriTemplateHandler handler = new LocalHostUriTemplateHandler(environment);
assertThat(handler.getRootUri()).isEqualTo("http://localhost:1234");
}
@Test
void getRootUriWhenLocalServerPortMissingShouldUsePort8080() {
MockEnvironment environment = new MockEnvironment();
LocalHostUriTemplateHandler handler = new LocalHostUriTemplateHandler(environment);
assertThat(handler.getRootUri()).isEqualTo("http://localhost:8080");
}
@Test
void getRootUriUsesCustomScheme() {
MockEnvironment environment = new MockEnvironment();
LocalHostUriTemplateHandler handler = new LocalHostUriTemplateHandler(environment, "https");
assertThat(handler.getRootUri()).isEqualTo("https://localhost:8080");
}
@Test
void getRootUriShouldUseContextPath() {
MockEnvironment environment = new MockEnvironment();
environment.setProperty("server.servlet.context-path", "/foo");
LocalHostUriTemplateHandler handler = new LocalHostUriTemplateHandler(environment);
assertThat(handler.getRootUri()).isEqualTo("http://localhost:8080/foo");
}
@Test
void expandShouldUseCustomHandler() {
MockEnvironment environment = new MockEnvironment();
UriTemplateHandler uriTemplateHandler = mock(UriTemplateHandler.class);
Map<String, ?> uriVariables = new HashMap<>();
URI uri = URI.create("https://www.example.com");
given(uriTemplateHandler.expand("https://localhost:8080/", uriVariables)).willReturn(uri);
LocalHostUriTemplateHandler handler = new LocalHostUriTemplateHandler(environment, "https", uriTemplateHandler);
assertThat(handler.expand("/", uriVariables)).isEqualTo(uri);
then(uriTemplateHandler).should().expand("https://localhost:8080/", uriVariables);
}
}
@@ -1,47 +0,0 @@
/*
* 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 org.springframework.boot.web.server.test.client;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.test.web.servlet.client.RestTestClient;
import static org.assertj.core.api.Assertions.assertThat;
/**
* {@link ImportSelector} to check no {@link RestTestClient} definition is registered when
* config classes are processed.
*/
class NoRestTestClientBeanChecker implements ImportSelector, BeanFactoryAware {
@Override
public void setBeanFactory(BeanFactory beanFactory) {
assertThat(BeanFactoryUtils.beanNamesForTypeIncludingAncestors((ListableBeanFactory) beanFactory,
RestTestClient.class))
.isEmpty();
}
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[0];
}
}
@@ -1,46 +0,0 @@
/*
* 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 org.springframework.boot.web.server.test.client;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
import static org.assertj.core.api.Assertions.assertThat;
/**
* {@link ImportSelector} to check no {@link TestRestTemplate} definition is registered
* when config classes are processed.
*/
class NoTestRestTemplateBeanChecker implements ImportSelector, BeanFactoryAware {
@Override
public void setBeanFactory(BeanFactory beanFactory) {
assertThat(BeanFactoryUtils.beanNamesForTypeIncludingAncestors((ListableBeanFactory) beanFactory,
TestRestTemplate.class))
.isEmpty();
}
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[0];
}
}
@@ -1,74 +0,0 @@
/*
* 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 org.springframework.boot.web.server.test.client;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.web.servlet.client.RestTestClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.then;
import static org.mockito.Mockito.mock;
/**
* Integration test for {@link RestTestClientContextCustomizer}.
*
* @author Stephane Nicoll
*/
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@DirtiesContext
class RestTestClientContextCustomizerIntegrationTests {
@Autowired
private RestTestClient webClient;
@Autowired
private RestTestClientBuilderCustomizer clientBuilderCustomizer;
@Test
void test() {
then(this.clientBuilderCustomizer).should().customize(any(RestTestClient.Builder.class));
this.webClient.get().uri("/").exchange().expectBody(String.class).isEqualTo("hello");
}
@Configuration(proxyBeanMethods = false)
@Import({ TestWebMvcConfiguration.class, NoRestTestClientBeanChecker.class })
@RestController
static class TestConfig {
@GetMapping("/")
String root() {
return "hello";
}
@Bean
RestTestClientBuilderCustomizer clientBuilderCustomizer() {
return mock(RestTestClientBuilderCustomizer.class);
}
}
}
@@ -1,92 +0,0 @@
/*
* 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 org.springframework.boot.web.server.test.client;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.web.server.test.client.RestTestClientContextCustomizer.RestTestClientRegistrar;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.test.context.MergedContextConfiguration;
import org.springframework.test.web.servlet.client.RestTestClient;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link RestTestClientContextCustomizer}.
*
* @author Moritz Halbritter
*/
class RestTestClientContextCustomizerTests {
@Test
void whenContextIsNotABeanDefinitionRegistryRestTestClientIsRegistered() {
new ApplicationContextRunner(TestApplicationContext::new)
.withInitializer(this::applyRestTestClientContextCustomizer)
.run((context) -> assertThat(context).hasSingleBean(RestTestClient.class));
}
@Test
void whenUsingAotGeneratedArtifactsRestTestClientIsNotRegistered() {
new ApplicationContextRunner().withSystemProperties("spring.aot.enabled:true")
.withInitializer(this::applyRestTestClientContextCustomizer)
.run((context) -> {
assertThat(context).doesNotHaveBean(RestTestClientRegistrar.class);
assertThat(context).doesNotHaveBean(RestTestClient.class);
});
}
@SuppressWarnings({ "unchecked", "rawtypes" })
void applyRestTestClientContextCustomizer(ConfigurableApplicationContext context) {
MergedContextConfiguration configuration = mock(MergedContextConfiguration.class);
given(configuration.getTestClass()).willReturn((Class) TestClass.class);
new RestTestClientContextCustomizer().customizeContext(context, configuration);
}
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
static class TestClass {
}
static class TestApplicationContext extends AbstractApplicationContext {
private final ConfigurableListableBeanFactory beanFactory = new DefaultListableBeanFactory();
@Override
protected void refreshBeanFactory() {
}
@Override
protected void closeBeanFactory() {
}
@Override
public ConfigurableListableBeanFactory getBeanFactory() {
return this.beanFactory;
}
}
}
@@ -1,88 +0,0 @@
/*
* 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 org.springframework.boot.web.server.test.client;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.tomcat.servlet.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.servlet.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.web.servlet.client.RestTestClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.DispatcherServlet;
/**
* Integration test for {@link RestTestClientContextCustomizer} with a custom context
* path.
*
* @author Stephane Nicoll
*/
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@TestPropertySource(properties = "server.servlet.context-path=/test")
class RestTestClientContextCustomizerWithCustomContextPathIntegrationTests {
@Autowired
private RestTestClient webClient;
@Test
void test() {
this.webClient.get().uri("/").exchange().expectBody(String.class).isEqualTo("hello");
}
@Configuration(proxyBeanMethods = false)
@Import(NoRestTestClientBeanChecker.class)
@RestController
static class TestConfig {
@Value("${server.port:8080}")
private int port = 8080;
@Bean
DispatcherServlet dispatcherServlet() {
return new DispatcherServlet();
}
@Bean
ServletWebServerFactory webServerFactory() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
factory.setPort(this.port);
factory.setContextPath("/test");
return factory;
}
@Bean
static PropertySourcesPlaceholderConfigurer propertyPlaceholder() {
return new PropertySourcesPlaceholderConfigurer();
}
@GetMapping("/")
String root() {
return "hello";
}
}
}
@@ -1,71 +0,0 @@
/*
* 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 org.springframework.boot.web.server.test.client;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.test.web.servlet.client.RestTestClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
/**
* Integration test for {@link RestTestClientContextCustomizer} with a custom client.
*
* @author Stephane Nicoll
*/
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class RestTestClientContextCustomizerWithOverridePathIntegrationTests {
@Autowired
private RestTestClient webClient;
@Test
void test() {
assertThat(this.webClient).isInstanceOf(CustomRestTestClient.class);
}
@Configuration(proxyBeanMethods = false)
@Import({ TestWebMvcConfiguration.class, NoRestTestClientBeanChecker.class })
@RestController
static class TestConfig {
@GetMapping("/")
String root() {
return "hello";
}
@Bean
CustomRestTestClient customRestTestClient() {
return mock(CustomRestTestClient.class);
}
}
interface CustomRestTestClient extends RestTestClient {
}
}
@@ -1,78 +0,0 @@
/*
* 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 org.springframework.boot.web.server.test.client;
import java.io.IOException;
import java.io.PrintWriter;
import jakarta.servlet.GenericServlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.tomcat.servlet.TomcatServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.test.annotation.DirtiesContext;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link TestRestTemplateContextCustomizer}.
*
* @author Phillip Webb
*/
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@DirtiesContext
class TestRestTemplateContextCustomizerIntegrationTests {
@Autowired
private TestRestTemplate restTemplate;
@Test
void test() {
assertThat(this.restTemplate.getForObject("/", String.class)).contains("hello");
}
@Configuration(proxyBeanMethods = false)
@Import({ TestServlet.class, NoTestRestTemplateBeanChecker.class })
static class TestConfig {
@Bean
TomcatServletWebServerFactory webServerFactory() {
return new TomcatServletWebServerFactory(0);
}
}
static class TestServlet extends GenericServlet {
@Override
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
try (PrintWriter writer = response.getWriter()) {
writer.println("hello");
}
}
}
}
@@ -1,91 +0,0 @@
/*
* 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 org.springframework.boot.web.server.test.client;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.web.server.test.client.TestRestTemplateContextCustomizer.TestRestTemplateRegistrar;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.test.context.MergedContextConfiguration;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.BDDMockito.given;
import static org.mockito.Mockito.mock;
/**
* Tests for {@link TestRestTemplateContextCustomizer}.
*
* @author Andy Wilkinson
*/
class TestRestTemplateContextCustomizerTests {
@Test
void whenContextIsNotABeanDefinitionRegistryTestRestTemplateIsRegistered() {
new ApplicationContextRunner(TestApplicationContext::new)
.withInitializer(this::applyTestRestTemplateContextCustomizer)
.run((context) -> assertThat(context).hasSingleBean(TestRestTemplate.class));
}
@Test
void whenUsingAotGeneratedArtifactsTestRestTemplateIsNotRegistered() {
new ApplicationContextRunner().withSystemProperties("spring.aot.enabled:true")
.withInitializer(this::applyTestRestTemplateContextCustomizer)
.run((context) -> {
assertThat(context).doesNotHaveBean(TestRestTemplateRegistrar.class);
assertThat(context).doesNotHaveBean(TestRestTemplate.class);
});
}
@SuppressWarnings({ "unchecked", "rawtypes" })
void applyTestRestTemplateContextCustomizer(ConfigurableApplicationContext context) {
MergedContextConfiguration configuration = mock(MergedContextConfiguration.class);
given(configuration.getTestClass()).willReturn((Class) TestClass.class);
new TestRestTemplateContextCustomizer().customizeContext(context, configuration);
}
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
static class TestClass {
}
static class TestApplicationContext extends AbstractApplicationContext {
private final ConfigurableListableBeanFactory beanFactory = new DefaultListableBeanFactory();
@Override
protected void refreshBeanFactory() {
}
@Override
protected void closeBeanFactory() {
}
@Override
public ConfigurableListableBeanFactory getBeanFactory() {
return this.beanFactory;
}
}
}
@@ -1,62 +0,0 @@
/*
* 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 org.springframework.boot.web.server.test.client;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.tomcat.servlet.TomcatServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.annotation.DirtiesContext;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link TestRestTemplateContextCustomizer} to ensure
* early-initialization of factory beans doesn't occur.
*
* @author Madhura Bhave
*/
@SpringBootTest(classes = TestRestTemplateContextCustomizerWithFactoryBeanTests.TestClassWithFactoryBean.class,
webEnvironment = WebEnvironment.RANDOM_PORT)
@DirtiesContext
class TestRestTemplateContextCustomizerWithFactoryBeanTests {
@Autowired
private TestRestTemplate restTemplate;
@Test
void test() {
assertThat(this.restTemplate).isNotNull();
}
@Configuration(proxyBeanMethods = false)
@ComponentScan("org.springframework.boot.test.web.client.scan")
static class TestClassWithFactoryBean {
@Bean
TomcatServletWebServerFactory webServerFactory() {
return new TomcatServletWebServerFactory(0);
}
}
}
@@ -1,88 +0,0 @@
/*
* 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 org.springframework.boot.web.server.test.client;
import java.io.IOException;
import java.io.PrintWriter;
import jakarta.servlet.GenericServlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.tomcat.servlet.TomcatServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.test.annotation.DirtiesContext;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link TestRestTemplateContextCustomizer} with a custom
* {@link TestRestTemplate} bean.
*
* @author Phillip Webb
*/
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@DirtiesContext
class TestRestTemplateContextCustomizerWithOverrideIntegrationTests {
@Autowired
private TestRestTemplate restTemplate;
@Test
void test() {
assertThat(this.restTemplate).isInstanceOf(CustomTestRestTemplate.class);
}
@Configuration(proxyBeanMethods = false)
@Import({ TestServlet.class, NoTestRestTemplateBeanChecker.class })
static class TestConfig {
@Bean
TomcatServletWebServerFactory webServerFactory() {
return new TomcatServletWebServerFactory(0);
}
@Bean
TestRestTemplate template() {
return new CustomTestRestTemplate();
}
}
static class TestServlet extends GenericServlet {
@Override
public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
try (PrintWriter writer = response.getWriter()) {
writer.println("hello");
}
}
}
static class CustomTestRestTemplate extends TestRestTemplate {
}
}
@@ -1,52 +0,0 @@
/*
* 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 org.springframework.boot.web.server.test.client;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.tomcat.servlet.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.servlet.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@Configuration(proxyBeanMethods = false)
@EnableWebMvc
class TestWebMvcConfiguration {
@Value("${server.port:8080}")
private int port = 8080;
@Bean
DispatcherServlet dispatcherServlet() {
return new DispatcherServlet();
}
@Bean
ServletWebServerFactory webServerFactory() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
factory.setPort(this.port);
return factory;
}
@Bean
static PropertySourcesPlaceholderConfigurer propertyPlaceholder() {
return new PropertySourcesPlaceholderConfigurer();
}
}
@@ -22,7 +22,6 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.boot.test.http.server.BaseUrl;
import org.springframework.boot.test.http.server.BaseUrlProvider;
import org.springframework.boot.web.server.AbstractConfigurableWebServerFactory;
import org.springframework.boot.web.server.reactive.AbstractReactiveWebServerFactory;
import org.springframework.context.ApplicationContext;
/**
@@ -65,7 +64,7 @@ class ReactiveWebServerApplicationContextBaseUrlProvider implements BaseUrlProvi
private boolean isSslEnabled(ReactiveWebServerApplicationContext context) {
try {
AbstractConfigurableWebServerFactory webServerFactory = context
.getBean(AbstractReactiveWebServerFactory.class);
.getBean(AbstractConfigurableWebServerFactory.class);
return webServerFactory.getSsl() != null && webServerFactory.getSsl().isEnabled();
}
catch (NoSuchBeanDefinitionException ex) {
@@ -22,7 +22,6 @@ import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.boot.test.http.server.BaseUrl;
import org.springframework.boot.test.http.server.BaseUrlProvider;
import org.springframework.boot.web.server.AbstractConfigurableWebServerFactory;
import org.springframework.boot.web.server.reactive.AbstractReactiveWebServerFactory;
import org.springframework.context.ApplicationContext;
/**
@@ -65,7 +64,7 @@ class ServletWebServerApplicationContextBaseUrlProvider implements BaseUrlProvid
private boolean isSslEnabled(ServletWebServerApplicationContext context) {
try {
AbstractConfigurableWebServerFactory webServerFactory = context
.getBean(AbstractReactiveWebServerFactory.class);
.getBean(AbstractConfigurableWebServerFactory.class);
return webServerFactory.getSsl() != null && webServerFactory.getSsl().isEnabled();
}
catch (NoSuchBeanDefinitionException ex) {
@@ -22,7 +22,7 @@ import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.test.context.FilteredClassLoader;
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
import org.springframework.boot.test.web.reactive.client.WebTestClientBuilderCustomizer;
import org.springframework.boot.web.server.test.client.RestTestClientBuilderCustomizer;
import org.springframework.boot.test.web.servlet.client.RestTestClientBuilderCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.web.reactive.server.WebTestClient;
+1
View File
@@ -53,6 +53,7 @@ dependencies {
testImplementation(project(":core:spring-boot-test"))
testImplementation(project(":module:spring-boot-jackson"))
testImplementation(project(":module:spring-boot-restclient"))
testImplementation(project(":module:spring-boot-restclient-test"))
testImplementation(project(":module:spring-boot-tomcat"))
testImplementation(project(":module:spring-boot-web-server-test"))
testImplementation(project(":test-support:spring-boot-test-support"))
@@ -23,12 +23,12 @@ import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.http.converter.autoconfigure.HttpMessageConvertersAutoConfiguration;
import org.springframework.boot.restclient.test.TestRestTemplate;
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
import org.springframework.boot.testsupport.classpath.resources.WithResource;
import org.springframework.boot.tomcat.autoconfigure.servlet.TomcatServletWebServerAutoConfiguration;
import org.springframework.boot.web.server.context.WebServerApplicationContext;
import org.springframework.boot.web.server.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.boot.web.server.test.client.TestRestTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.RequestEntity;
@@ -40,11 +40,11 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.http.converter.autoconfigure.HttpMessageConvertersAutoConfiguration;
import org.springframework.boot.restclient.test.TestRestTemplate;
import org.springframework.boot.tomcat.autoconfigure.servlet.TomcatServletWebServerAutoConfiguration;
import org.springframework.boot.web.error.ErrorAttributeOptions;
import org.springframework.boot.web.error.ErrorAttributeOptions.Include;
import org.springframework.boot.web.server.autoconfigure.ServerProperties;
import org.springframework.boot.web.server.test.client.TestRestTemplate;
import org.springframework.boot.webmvc.autoconfigure.DispatcherServletAutoConfiguration;
import org.springframework.boot.webmvc.autoconfigure.WebMvcAutoConfiguration;
import org.springframework.boot.webmvc.error.ErrorAttributes;
@@ -21,6 +21,7 @@ import org.junit.jupiter.api.Test;
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.http.converter.autoconfigure.HttpMessageConvertersAutoConfiguration;
import org.springframework.boot.restclient.test.TestRestTemplate;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.tomcat.autoconfigure.servlet.TomcatServletWebServerAutoConfiguration;
@@ -28,7 +29,6 @@ import org.springframework.boot.web.error.ErrorPage;
import org.springframework.boot.web.error.ErrorPageRegistrar;
import org.springframework.boot.web.error.ErrorPageRegistry;
import org.springframework.boot.web.server.test.LocalServerPort;
import org.springframework.boot.web.server.test.client.TestRestTemplate;
import org.springframework.boot.webmvc.autoconfigure.DispatcherServletAutoConfiguration;
import org.springframework.boot.webmvc.autoconfigure.WebMvcAutoConfiguration;
import org.springframework.context.annotation.Configuration;