Browse Source

Introduce spring-boot-webclient-test

See gh-46356
See gh-47322
pull/47549/head
Andy Wilkinson 4 months ago
parent
commit
885f90da0c
  1. 1
      documentation/spring-boot-docs/build.gradle
  2. 14
      documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/testing/spring-boot-applications.adoc
  3. 3
      documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/testing/test-modules.adoc
  4. 42
      module/spring-boot-webclient-test/build.gradle
  5. 45
      module/spring-boot-webclient-test/src/main/java/org/springframework/boot/webclient/test/autoconfigure/AutoConfigureWebClient.java
  6. 129
      module/spring-boot-webclient-test/src/main/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTest.java
  7. 29
      module/spring-boot-webclient-test/src/main/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestContextBootstrapper.java
  8. 74
      module/spring-boot-webclient-test/src/main/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTypeExcludeFilter.java
  9. 23
      module/spring-boot-webclient-test/src/main/java/org/springframework/boot/webclient/test/autoconfigure/package-info.java
  10. 2
      module/spring-boot-webclient-test/src/main/resources/META-INF/spring/org.springframework.boot.webclient.test.autoconfigure.AutoConfigureWebClient.imports
  11. 47
      module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/AnotherExampleWebClientService.java
  12. 43
      module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/ExampleProperties.java
  13. 32
      module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/ExampleWebClientApplication.java
  14. 52
      module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/ExampleWebClientService.java
  15. 69
      module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/MockWebServerConfiguration.java
  16. 66
      module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestIntegrationTests.java
  17. 70
      module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestNoComponentIntegrationTests.java
  18. 59
      module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestPropertiesIntegrationTests.java
  19. 46
      module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestWithConfigurationPropertiesIntegrationTests.java
  20. 56
      module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestWithoutJacksonIntegrationTests.java
  21. 1
      platform/spring-boot-dependencies/build.gradle
  22. 1
      settings.gradle
  23. 2
      starter/spring-boot-starter-webclient-test/build.gradle

1
documentation/spring-boot-docs/build.gradle

@ -128,6 +128,7 @@ dependencies { @@ -128,6 +128,7 @@ dependencies {
implementation(project(path: ":module:spring-boot-security"))
implementation(project(path: ":module:spring-boot-tomcat"))
implementation(project(path: ":module:spring-boot-webclient"))
implementation(project(path: ":module:spring-boot-webclient-test"))
implementation(project(path: ":module:spring-boot-webflux"))
implementation(project(path: ":module:spring-boot-webflux-test"))
implementation(project(path: ":module:spring-boot-webmvc"))

14
documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/testing/spring-boot-applications.adoc

@ -729,6 +729,20 @@ include-code::MyRestClientServiceTests[] @@ -729,6 +729,20 @@ include-code::MyRestClientServiceTests[]
[[testing.spring-boot-applications.autoconfigured-web-client]]
== Auto-configured Web Clients
You can use the javadoc:org.springframework.boot.webclient.test.autoconfigure.WebClientTest[format=annotation] annotation from the `spring-boot-webclient-test` module to test code that uses `WebClient`.
By default, it auto-configures Jackson, GSON, and Jsonb support, and configures a javadoc:org.springframework.web.reactive.function.client.WebClient$Builder[].
Regular javadoc:org.springframework.stereotype.Component[format=annotation] and javadoc:org.springframework.boot.context.properties.ConfigurationProperties[format=annotation] beans are not scanned when the javadoc:org.springframework.boot.webclient.test.autoconfigure.WebClientTest[format=annotation] annotation is used.
javadoc:org.springframework.boot.context.properties.EnableConfigurationProperties[format=annotation] can be used to include javadoc:org.springframework.boot.context.properties.ConfigurationProperties[format=annotation] beans.
TIP: A list of the auto-configuration settings that are enabled by javadoc:org.springframework.boot.webclient.test.autoconfigure.WebClientTest[format=annotation] can be xref:appendix:test-auto-configuration/index.adoc[found in the appendix].
The specific beans that you want to test should be specified by using the `value` or `components` attribute of javadoc:org.springframework.boot.webclient.test.autoconfigure.WebClientTest[format=annotation].
[[testing.spring-boot-applications.autoconfigured-spring-restdocs]]
== Auto-configured Spring REST Docs Tests

3
documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/testing/test-modules.adoc

@ -64,6 +64,9 @@ Spring Boot offers several focused, feature-specific `-test` modules: @@ -64,6 +64,9 @@ Spring Boot offers several focused, feature-specific `-test` modules:
|`spring-boot-security-test`
|Testing applications that use Spring Security.
|`spring-boot-webclient-test`
|Testing applications that use `WebClient`. Provides the `@WebClientTest` test slice.
|`spring-boot-webflux-test`
|Testing applications that use Spring WebFlux. Provides the `@WebFluxTest` test slice.

42
module/spring-boot-webclient-test/build.gradle

@ -0,0 +1,42 @@ @@ -0,0 +1,42 @@
/*
* 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.
*/
plugins {
id "java-library"
id "org.springframework.boot.deployed"
id "org.springframework.boot.optional-dependencies"
id "org.springframework.boot.test-slice"
}
description = "Spring Boot WebClient Test"
dependencies {
api(project(":core:spring-boot-test-autoconfigure"))
api(project(":module:spring-boot-webclient"))
optional(project(":core:spring-boot-autoconfigure"))
optional(project(":module:spring-boot-jackson"))
optional("org.apache.httpcomponents.client5:httpclient5")
optional("org.junit.jupiter:junit-jupiter-api")
optional("org.springframework:spring-test")
testImplementation(project(":core:spring-boot-test"))
testImplementation(project(":module:spring-boot-micrometer-metrics"))
testImplementation(project(":test-support:spring-boot-test-support"))
testImplementation("com.squareup.okhttp3:mockwebserver")
testRuntimeOnly("ch.qos.logback:logback-classic")
}

45
module/spring-boot-webclient-test/src/main/java/org/springframework/boot/webclient/test/autoconfigure/AutoConfigureWebClient.java

@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
/*
* 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.webclient.test.autoconfigure;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.test.autoconfigure.json.AutoConfigureJson;
import org.springframework.web.client.RestClient.Builder;
/**
* Annotation that can be applied to a test class to enable auto-configuration of a
* {@link Builder WebClient.Builder}.
*
* @author Andy Wilkinson
* @since 4.0.0
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigureJson
@ImportAutoConfiguration
public @interface AutoConfigureWebClient {
}

129
module/spring-boot-webclient-test/src/main/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTest.java

@ -0,0 +1,129 @@ @@ -0,0 +1,129 @@
/*
* 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.webclient.test.autoconfigure;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.test.autoconfigure.OverrideAutoConfiguration;
import org.springframework.boot.test.context.filter.annotation.TypeExcludeFilters;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.core.annotation.AliasFor;
import org.springframework.core.env.Environment;
import org.springframework.test.context.BootstrapWith;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.web.client.RestClient.Builder;
/**
* Annotation for a Spring WebClient test that focuses <strong>only</strong> on beans that
* use {@link Builder WebClient.Builder}.
* <p>
* Using this annotation only enables auto-configuration that is relevant to rest client
* tests. Similarly, component scanning is limited to beans annotated with:
* <ul>
* <li>{@code @JsonComponent}</li>
* </ul>
* <p>
* as well as beans that implement:
* <ul>
* <li>{@code JacksonModule}, if Jackson is available</li>
* </ul>
* <p>
* When using JUnit 4, this annotation should be used in combination with
* {@code @RunWith(SpringRunner.class)}.
*
* @author Andy Wilkinson
* @since 4.0.0
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@BootstrapWith(WebClientTestContextBootstrapper.class)
@ExtendWith(SpringExtension.class)
@OverrideAutoConfiguration(enabled = false)
@TypeExcludeFilters(WebClientTypeExcludeFilter.class)
@AutoConfigureWebClient
@ImportAutoConfiguration
public @interface WebClientTest {
/**
* Properties in form {@literal key=value} that should be added to the Spring
* {@link Environment} before the test runs.
* @return the properties to add
*/
String[] properties() default {};
/**
* Specifies the components to test. This is an alias of {@link #components()} which
* can be used for brevity if no other attributes are defined. See
* {@link #components()} for details.
* @see #components()
* @return the components to test
*/
@AliasFor("components")
Class<?>[] value() default {};
/**
* Specifies the components to test. May be left blank if components will be manually
* imported or created directly.
* @see #value()
* @return the components to test
*/
@AliasFor("value")
Class<?>[] components() default {};
/**
* Determines if default filtering should be used with
* {@link SpringBootApplication @SpringBootApplication}. By default only
* {@code @JsonComponent} and {@code Module} beans are included.
* @see #includeFilters()
* @see #excludeFilters()
* @return if default filters should be used
*/
boolean useDefaultFilters() default true;
/**
* A set of include filters which can be used to add otherwise filtered beans to the
* application context.
* @return include filters to apply
*/
ComponentScan.Filter[] includeFilters() default {};
/**
* A set of exclude filters which can be used to filter beans that would otherwise be
* added to the application context.
* @return exclude filters to apply
*/
ComponentScan.Filter[] excludeFilters() default {};
/**
* Auto-configuration exclusions that should be applied for this test.
* @return auto-configuration exclusions to apply
*/
@AliasFor(annotation = ImportAutoConfiguration.class, attribute = "exclude")
Class<?>[] excludeAutoConfiguration() default {};
}

29
module/spring-boot-webclient-test/src/main/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestContextBootstrapper.java

@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
/*
* 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.webclient.test.autoconfigure;
import org.springframework.boot.test.autoconfigure.TestSliceTestContextBootstrapper;
import org.springframework.test.context.TestContextBootstrapper;
/**
* {@link TestContextBootstrapper} for {@link WebClientTest @WebClientTest} support.
*
* @author Andy Wilkinson
*/
class WebClientTestContextBootstrapper extends TestSliceTestContextBootstrapper<WebClientTest> {
}

74
module/spring-boot-webclient-test/src/main/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTypeExcludeFilter.java

@ -0,0 +1,74 @@ @@ -0,0 +1,74 @@
/*
* 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.webclient.test.autoconfigure;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import org.springframework.boot.context.TypeExcludeFilter;
import org.springframework.boot.jackson.JsonComponent;
import org.springframework.boot.test.context.filter.annotation.StandardAnnotationCustomizableTypeExcludeFilter;
import org.springframework.util.ClassUtils;
/**
* {@link TypeExcludeFilter} for {@link WebClientTest @WebClientTest}.
*
* @author Andy Wilkinson
*/
class WebClientTypeExcludeFilter extends StandardAnnotationCustomizableTypeExcludeFilter<WebClientTest> {
private static final Class<?>[] NO_COMPONENTS = {};
private static final String DATABIND_MODULE_CLASS_NAME = "tools.jackson.databind.JacksonModule";
private static final Set<Class<?>> KNOWN_INCLUDES;
static {
Set<Class<?>> includes = new LinkedHashSet<>();
if (ClassUtils.isPresent(DATABIND_MODULE_CLASS_NAME, WebClientTypeExcludeFilter.class.getClassLoader())) {
try {
includes.add(Class.forName(DATABIND_MODULE_CLASS_NAME, true,
WebClientTypeExcludeFilter.class.getClassLoader()));
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException("Failed to load " + DATABIND_MODULE_CLASS_NAME, ex);
}
includes.add(JsonComponent.class);
}
KNOWN_INCLUDES = Collections.unmodifiableSet(includes);
}
private final Class<?>[] components;
WebClientTypeExcludeFilter(Class<?> testClass) {
super(testClass);
this.components = getAnnotation().getValue("components", Class[].class).orElse(NO_COMPONENTS);
}
@Override
protected Set<Class<?>> getKnownIncludes() {
return KNOWN_INCLUDES;
}
@Override
protected Set<Class<?>> getComponentIncludes() {
return new LinkedHashSet<>(Arrays.asList(this.components));
}
}

23
module/spring-boot-webclient-test/src/main/java/org/springframework/boot/webclient/test/autoconfigure/package-info.java

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
/*
* 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.
*/
/**
* Auto-configuration for web clients.
*/
@NullMarked
package org.springframework.boot.webclient.test.autoconfigure;
import org.jspecify.annotations.NullMarked;

2
module/spring-boot-webclient-test/src/main/resources/META-INF/spring/org.springframework.boot.webclient.test.autoconfigure.AutoConfigureWebClient.imports

@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
org.springframework.boot.http.codec.autoconfigure.CodecsAutoConfiguration
org.springframework.boot.webclient.autoconfigure.WebClientAutoConfiguration

47
module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/AnotherExampleWebClientService.java

@ -0,0 +1,47 @@ @@ -0,0 +1,47 @@
/*
* 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.webclient.test.autoconfigure;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
/**
* A second example web client used with {@link WebClientTest @WebClientTest} tests.
*
* @author Scott Frederick
*/
@Service
public class AnotherExampleWebClientService {
private final WebClient.Builder builder;
private final WebClient webClient;
public AnotherExampleWebClientService(WebClient.Builder builder) {
this.builder = builder;
this.webClient = builder.baseUrl("https://example.com").build();
}
protected WebClient.Builder geWebClientBuilder() {
return this.builder;
}
public String test() {
return this.webClient.get().uri("/test").retrieve().toEntity(String.class).block().getBody();
}
}

43
module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/ExampleProperties.java

@ -0,0 +1,43 @@ @@ -0,0 +1,43 @@
/*
* 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.webclient.test.autoconfigure;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.ConstructorBinding;
import org.springframework.boot.context.properties.bind.DefaultValue;
/**
* Example {@link ConstructorBinding constructor-bound}
* {@link ConfigurationProperties @ConfigurationProperties} used to test the use of
* configuration properties scan with sliced test.
*
* @author Stephane Nicoll
*/
@ConfigurationProperties("example")
public class ExampleProperties {
private final String name;
public ExampleProperties(@DefaultValue("test") String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}

32
module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/ExampleWebClientApplication.java

@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
/*
* 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.webclient.test.autoconfigure;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.ConfigurationPropertiesScan;
/**
* Example {@link SpringBootApplication @SpringBootApplication} used with
* {@link WebClientTest @WebClientTest} tests.
*
* @author Phillip Webb
*/
@SpringBootApplication
@ConfigurationPropertiesScan
public class ExampleWebClientApplication {
}

52
module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/ExampleWebClientService.java

@ -0,0 +1,52 @@ @@ -0,0 +1,52 @@
/*
* 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.webclient.test.autoconfigure;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
/**
* Example web client using {@code WebClient} with {@link WebClientTest @WebClientTest}
* tests.
*
* @author Scott Frederick
*/
@Service
public class ExampleWebClientService {
private final WebClient.Builder builder;
private final WebClient webClient;
public ExampleWebClientService(WebClient.Builder builder) {
this.builder = builder;
this.webClient = builder.build();
}
protected WebClient.Builder getWebClientBuilder() {
return this.builder;
}
public String test() {
return this.webClient.get().uri("/test").retrieve().toEntity(String.class).block().getBody();
}
public void testPostWithBody(String body) {
this.webClient.post().uri("/test").bodyValue(body).retrieve().toBodilessEntity().block();
}
}

69
module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/MockWebServerConfiguration.java

@ -0,0 +1,69 @@ @@ -0,0 +1,69 @@
/*
* 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.webclient.test.autoconfigure;
import java.io.IOException;
import java.io.UncheckedIOException;
import okhttp3.mockwebserver.MockWebServer;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.boot.webclient.WebClientCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.reactive.function.client.WebClient;
/**
* Configuration for a {@link MockWebServer}.
*
* @author Andy Wilkinson
*/
@Configuration(proxyBeanMethods = false)
public class MockWebServerConfiguration implements DisposableBean, WebClientCustomizer {
private final MockWebServer mockWebServer = new MockWebServer();
MockWebServerConfiguration() {
try {
this.mockWebServer.start();
}
catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
@Override
public void destroy() {
try {
this.mockWebServer.shutdown();
}
catch (IOException ex) {
throw new UncheckedIOException(ex);
}
}
@Override
public void customize(WebClient.Builder webClientBuilder) {
webClientBuilder.baseUrl(this.mockWebServer.url("/").toString());
}
@Bean
MockWebServer mockWebServer() {
return this.mockWebServer;
}
}

66
module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestIntegrationTests.java

@ -0,0 +1,66 @@ @@ -0,0 +1,66 @@
/*
* 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.webclient.test.autoconfigure;
import java.nio.charset.StandardCharsets;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Import;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link WebClientTest @WebClientTest}.
*
* @author Scott Frederick
*/
@WebClientTest(ExampleWebClientService.class)
@Import(MockWebServerConfiguration.class)
class WebClientTestIntegrationTests {
@Autowired
private MockWebServer server;
@Autowired
private ExampleWebClientService client;
@Test
void mockServerCall1() throws InterruptedException {
this.server.enqueue(new MockResponse().setBody("1"));
assertThat(this.client.test()).isEqualTo("1");
this.server.takeRequest();
}
@Test
void mockServerCall2() throws InterruptedException {
this.server.enqueue(new MockResponse().setBody("2"));
assertThat(this.client.test()).isEqualTo("2");
this.server.takeRequest();
}
@Test
void mockServerCallWithContent() throws InterruptedException {
this.server.enqueue(new MockResponse().setBody("1"));
this.client.testPostWithBody("test");
assertThat(this.server.takeRequest().getBody().readString(StandardCharsets.UTF_8)).isEqualTo("test");
}
}

70
module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestNoComponentIntegrationTests.java

@ -0,0 +1,70 @@ @@ -0,0 +1,70 @@
/*
* 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.webclient.test.autoconfigure;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Import;
import org.springframework.web.reactive.function.client.WebClient;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
/**
* Tests for {@link WebClientTest @WebClientTest} with no specific client.
*
* @author Phillip Webb
*/
@WebClientTest
@Import(MockWebServerConfiguration.class)
class WebClientTestNoComponentIntegrationTests {
@Autowired
private MockWebServer server;
@Autowired
private ApplicationContext applicationContext;
@Autowired
private WebClient.Builder webClientBuilder;
@Test
void exampleWebClientServiceIsNotInjected() {
assertThatExceptionOfType(NoSuchBeanDefinitionException.class)
.isThrownBy(() -> this.applicationContext.getBean(ExampleWebClientService.class));
}
@Test
void examplePropertiesIsNotInjected() {
assertThatExceptionOfType(NoSuchBeanDefinitionException.class)
.isThrownBy(() -> this.applicationContext.getBean(ExampleProperties.class));
}
@Test
void manuallyCreateBean() throws InterruptedException {
ExampleWebClientService client = new ExampleWebClientService(this.webClientBuilder);
this.server.enqueue(new MockResponse().setBody("hello"));
assertThat(client.test()).isEqualTo("hello");
this.server.takeRequest();
}
}

59
module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestPropertiesIntegrationTests.java

@ -0,0 +1,59 @@ @@ -0,0 +1,59 @@
/*
* 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.webclient.test.autoconfigure;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.env.Environment;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for the {@link WebClientTest#properties properties} attribute of
* {@link WebClientTest @WebClientTest}.
*
* @author Artsiom Yudovin
*/
@WebClientTest(properties = "spring.profiles.active=test")
class WebClientTestPropertiesIntegrationTests {
@Autowired
private Environment environment;
@Test
void environmentWithNewProfile() {
assertThat(this.environment.getActiveProfiles()).containsExactly("test");
}
@Nested
class NestedTests {
@Autowired
private Environment innerEnvironment;
@Test
void propertiesFromEnclosingClassAffectNestedTests() {
assertThat(WebClientTestPropertiesIntegrationTests.this.environment.getActiveProfiles())
.containsExactly("test");
assertThat(this.innerEnvironment.getActiveProfiles()).containsExactly("test");
}
}
}

46
module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestWithConfigurationPropertiesIntegrationTests.java

@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
/*
* 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.webclient.test.autoconfigure;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link WebClientTest @WebClientTest} with a
* {@link ConfigurationProperties @ConfigurationProperties} annotated type.
*
* @author Stephane Nicoll
*/
@WebClientTest(components = ExampleProperties.class, properties = "example.name=Hello")
class WebClientTestWithConfigurationPropertiesIntegrationTests {
@Autowired
private ApplicationContext applicationContext;
@Test
void configurationPropertiesCanBeAddedAsComponent() {
assertThat(this.applicationContext.getBeansOfType(ExampleProperties.class).keySet())
.containsOnly("example-" + ExampleProperties.class.getName());
assertThat(this.applicationContext.getBean(ExampleProperties.class).getName()).isEqualTo("Hello");
}
}

56
module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestWithoutJacksonIntegrationTests.java

@ -0,0 +1,56 @@ @@ -0,0 +1,56 @@
/*
* 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.webclient.test.autoconfigure;
import okhttp3.mockwebserver.MockResponse;
import okhttp3.mockwebserver.MockWebServer;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.testsupport.classpath.ClassPathExclusions;
import org.springframework.context.annotation.Import;
import org.springframework.util.ClassUtils;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link WebClientTest @WebClientTest} without Jackson.
*
* @author Andy Wilkinson
*/
@ClassPathExclusions("jackson-*.jar")
@WebClientTest(ExampleWebClientService.class)
@Import(MockWebServerConfiguration.class)
class WebClientTestWithoutJacksonIntegrationTests {
@Autowired
private MockWebServer server;
@Autowired
private ExampleWebClientService client;
@Test
void webClientTestCanBeUsedWhenJacksonIsNotOnTheClassPath() throws InterruptedException {
ClassLoader classLoader = getClass().getClassLoader();
assertThat(ClassUtils.isPresent("com.fasterxml.jackson.databind.Module", classLoader)).isFalse();
assertThat(ClassUtils.isPresent("tools.jackson.databind.JacksonModule", classLoader)).isFalse();
this.server.enqueue(new MockResponse().setBody("hello"));
assertThat(this.client.test()).isEqualTo("hello");
this.server.takeRequest();
}
}

1
platform/spring-boot-dependencies/build.gradle

@ -2260,6 +2260,7 @@ bom { @@ -2260,6 +2260,7 @@ bom {
"spring-boot-validation",
"spring-boot-web-server",
"spring-boot-webclient",
"spring-boot-webclient-test",
"spring-boot-webflux",
"spring-boot-webflux-test",
"spring-boot-webmvc",

1
settings.gradle

@ -189,6 +189,7 @@ include "module:spring-boot-tx" @@ -189,6 +189,7 @@ include "module:spring-boot-tx"
include "module:spring-boot-validation"
include "module:spring-boot-web-server"
include "module:spring-boot-webclient"
include "module:spring-boot-webclient-test"
include "module:spring-boot-webflux"
include "module:spring-boot-webflux-test"
include "module:spring-boot-webmvc"

2
starter/spring-boot-starter-webclient-test/build.gradle

@ -24,4 +24,6 @@ dependencies { @@ -24,4 +24,6 @@ dependencies {
api(project(":starter:spring-boot-starter-jackson-test"))
api(project(":starter:spring-boot-starter-test"))
api(project(":starter:spring-boot-starter-webclient"))
api(project(":module:spring-boot-webclient-test"))
}

Loading…
Cancel
Save