diff --git a/documentation/spring-boot-docs/build.gradle b/documentation/spring-boot-docs/build.gradle
index 12ffdb60994..865e9bb6dc5 100644
--- a/documentation/spring-boot-docs/build.gradle
+++ b/documentation/spring-boot-docs/build.gradle
@@ -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"))
diff --git a/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/testing/spring-boot-applications.adoc b/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/testing/spring-boot-applications.adoc
index d73e3a1fc81..1bb88975e7a 100644
--- a/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/testing/spring-boot-applications.adoc
+++ b/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/testing/spring-boot-applications.adoc
@@ -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
diff --git a/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/testing/test-modules.adoc b/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/testing/test-modules.adoc
index f1664260821..6ff48d410e4 100644
--- a/documentation/spring-boot-docs/src/docs/antora/modules/reference/pages/testing/test-modules.adoc
+++ b/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:
|`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.
diff --git a/module/spring-boot-webclient-test/build.gradle b/module/spring-boot-webclient-test/build.gradle
new file mode 100644
index 00000000000..00a7b00d94a
--- /dev/null
+++ b/module/spring-boot-webclient-test/build.gradle
@@ -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")
+}
diff --git a/module/spring-boot-webclient-test/src/main/java/org/springframework/boot/webclient/test/autoconfigure/AutoConfigureWebClient.java b/module/spring-boot-webclient-test/src/main/java/org/springframework/boot/webclient/test/autoconfigure/AutoConfigureWebClient.java
new file mode 100644
index 00000000000..44fcfcd8e88
--- /dev/null
+++ b/module/spring-boot-webclient-test/src/main/java/org/springframework/boot/webclient/test/autoconfigure/AutoConfigureWebClient.java
@@ -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 {
+
+}
diff --git a/module/spring-boot-webclient-test/src/main/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTest.java b/module/spring-boot-webclient-test/src/main/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTest.java
new file mode 100644
index 00000000000..04eedadbc7d
--- /dev/null
+++ b/module/spring-boot-webclient-test/src/main/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTest.java
@@ -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 only on beans that
+ * use {@link Builder WebClient.Builder}.
+ *
+ * Using this annotation only enables auto-configuration that is relevant to rest client
+ * tests. Similarly, component scanning is limited to beans annotated with:
+ *
+ * - {@code @JsonComponent}
+ *
+ *
+ * as well as beans that implement:
+ *
+ * - {@code JacksonModule}, if Jackson is available
+ *
+ *
+ * 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 {};
+
+}
diff --git a/module/spring-boot-webclient-test/src/main/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestContextBootstrapper.java b/module/spring-boot-webclient-test/src/main/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestContextBootstrapper.java
new file mode 100644
index 00000000000..3582c92a7e7
--- /dev/null
+++ b/module/spring-boot-webclient-test/src/main/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestContextBootstrapper.java
@@ -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 {
+
+}
diff --git a/module/spring-boot-webclient-test/src/main/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTypeExcludeFilter.java b/module/spring-boot-webclient-test/src/main/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTypeExcludeFilter.java
new file mode 100644
index 00000000000..9145738aefd
--- /dev/null
+++ b/module/spring-boot-webclient-test/src/main/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTypeExcludeFilter.java
@@ -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 {
+
+ private static final Class>[] NO_COMPONENTS = {};
+
+ private static final String DATABIND_MODULE_CLASS_NAME = "tools.jackson.databind.JacksonModule";
+
+ private static final Set> KNOWN_INCLUDES;
+
+ static {
+ Set> 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> getKnownIncludes() {
+ return KNOWN_INCLUDES;
+ }
+
+ @Override
+ protected Set> getComponentIncludes() {
+ return new LinkedHashSet<>(Arrays.asList(this.components));
+ }
+
+}
diff --git a/module/spring-boot-webclient-test/src/main/java/org/springframework/boot/webclient/test/autoconfigure/package-info.java b/module/spring-boot-webclient-test/src/main/java/org/springframework/boot/webclient/test/autoconfigure/package-info.java
new file mode 100644
index 00000000000..475427f41a5
--- /dev/null
+++ b/module/spring-boot-webclient-test/src/main/java/org/springframework/boot/webclient/test/autoconfigure/package-info.java
@@ -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;
diff --git a/module/spring-boot-webclient-test/src/main/resources/META-INF/spring/org.springframework.boot.webclient.test.autoconfigure.AutoConfigureWebClient.imports b/module/spring-boot-webclient-test/src/main/resources/META-INF/spring/org.springframework.boot.webclient.test.autoconfigure.AutoConfigureWebClient.imports
new file mode 100644
index 00000000000..7d602e14fd6
--- /dev/null
+++ b/module/spring-boot-webclient-test/src/main/resources/META-INF/spring/org.springframework.boot.webclient.test.autoconfigure.AutoConfigureWebClient.imports
@@ -0,0 +1,2 @@
+org.springframework.boot.http.codec.autoconfigure.CodecsAutoConfiguration
+org.springframework.boot.webclient.autoconfigure.WebClientAutoConfiguration
diff --git a/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/AnotherExampleWebClientService.java b/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/AnotherExampleWebClientService.java
new file mode 100644
index 00000000000..07193bb3d18
--- /dev/null
+++ b/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/AnotherExampleWebClientService.java
@@ -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();
+ }
+
+}
diff --git a/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/ExampleProperties.java b/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/ExampleProperties.java
new file mode 100644
index 00000000000..e51a5cd0ba3
--- /dev/null
+++ b/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/ExampleProperties.java
@@ -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;
+ }
+
+}
diff --git a/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/ExampleWebClientApplication.java b/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/ExampleWebClientApplication.java
new file mode 100644
index 00000000000..a65cd4c0006
--- /dev/null
+++ b/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/ExampleWebClientApplication.java
@@ -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 {
+
+}
diff --git a/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/ExampleWebClientService.java b/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/ExampleWebClientService.java
new file mode 100644
index 00000000000..7a05cd769e8
--- /dev/null
+++ b/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/ExampleWebClientService.java
@@ -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();
+ }
+
+}
diff --git a/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/MockWebServerConfiguration.java b/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/MockWebServerConfiguration.java
new file mode 100644
index 00000000000..cd6fc8ddbcf
--- /dev/null
+++ b/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/MockWebServerConfiguration.java
@@ -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;
+ }
+
+}
diff --git a/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestIntegrationTests.java b/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestIntegrationTests.java
new file mode 100644
index 00000000000..9947012f84f
--- /dev/null
+++ b/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestIntegrationTests.java
@@ -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");
+ }
+
+}
diff --git a/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestNoComponentIntegrationTests.java b/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestNoComponentIntegrationTests.java
new file mode 100644
index 00000000000..e243176677b
--- /dev/null
+++ b/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestNoComponentIntegrationTests.java
@@ -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();
+ }
+
+}
diff --git a/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestPropertiesIntegrationTests.java b/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestPropertiesIntegrationTests.java
new file mode 100644
index 00000000000..1a942ad40cf
--- /dev/null
+++ b/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestPropertiesIntegrationTests.java
@@ -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");
+ }
+
+ }
+
+}
diff --git a/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestWithConfigurationPropertiesIntegrationTests.java b/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestWithConfigurationPropertiesIntegrationTests.java
new file mode 100644
index 00000000000..9a5412fb1c0
--- /dev/null
+++ b/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestWithConfigurationPropertiesIntegrationTests.java
@@ -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");
+ }
+
+}
diff --git a/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestWithoutJacksonIntegrationTests.java b/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestWithoutJacksonIntegrationTests.java
new file mode 100644
index 00000000000..e126d62c41c
--- /dev/null
+++ b/module/spring-boot-webclient-test/src/test/java/org/springframework/boot/webclient/test/autoconfigure/WebClientTestWithoutJacksonIntegrationTests.java
@@ -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();
+ }
+
+}
diff --git a/platform/spring-boot-dependencies/build.gradle b/platform/spring-boot-dependencies/build.gradle
index 07613c3df6e..a48f549a56f 100644
--- a/platform/spring-boot-dependencies/build.gradle
+++ b/platform/spring-boot-dependencies/build.gradle
@@ -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",
diff --git a/settings.gradle b/settings.gradle
index 5c6ce4f3cfc..88ca33ee69a 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -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"
diff --git a/starter/spring-boot-starter-webclient-test/build.gradle b/starter/spring-boot-starter-webclient-test/build.gradle
index 9563edcc913..35c9ccf6023 100644
--- a/starter/spring-boot-starter-webclient-test/build.gradle
+++ b/starter/spring-boot-starter-webclient-test/build.gradle
@@ -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"))
}