diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebClientBuilder.java b/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebClientBuilder.java index 9764cea5c67..9374014421c 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebClientBuilder.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebClientBuilder.java @@ -24,15 +24,27 @@ import org.springframework.web.context.WebApplicationContext; import com.gargoylesoftware.htmlunit.WebClient; /** - * {@code MockMvcWebClientBuilder} simplifies the creation of a {@link WebClient} - * that delegates to a {@link MockMvc} instance. + * {@code MockMvcWebClientBuilder} simplifies the creation of an HtmlUnit + * {@link WebClient} that delegates to a {@link MockMvc} instance. + * + *

The {@code MockMvc} instance used by the builder may be + * {@linkplain #mockMvcSetup supplied directly} or created transparently + * from a {@link #webAppContextSetup WebApplicationContext}. * * @author Rob Winch * @author Sam Brannen * @since 4.2 + * @see #mockMvcSetup(MockMvc) + * @see #webAppContextSetup(WebApplicationContext) + * @see #webAppContextSetup(WebApplicationContext, MockMvcConfigurer) + * @see #withDelegate(WebClient) + * @see #build() */ public class MockMvcWebClientBuilder extends MockMvcWebConnectionBuilderSupport { + private WebClient webClient; + + protected MockMvcWebClientBuilder(MockMvc mockMvc) { super(mockMvc); } @@ -46,7 +58,19 @@ public class MockMvcWebClientBuilder extends MockMvcWebConnectionBuilderSupport< } /** - * Create a new instance with the supplied {@link WebApplicationContext}. + * Create a new {@code MockMvcWebClientBuilder} based on the supplied + * {@link MockMvc} instance. + * @param mockMvc the {@code MockMvc} instance to use; never {@code null} + * @return the MockMvcWebClientBuilder to customize + */ + public static MockMvcWebClientBuilder mockMvcSetup(MockMvc mockMvc) { + Assert.notNull(mockMvc, "MockMvc must not be null"); + return new MockMvcWebClientBuilder(mockMvc); + } + + /** + * Create a new {@code MockMvcWebClientBuilder} based on the supplied + * {@link WebApplicationContext}. * @param context the {@code WebApplicationContext} to create a {@link MockMvc} * instance from; never {@code null} * @return the MockMvcWebClientBuilder to customize @@ -57,8 +81,8 @@ public class MockMvcWebClientBuilder extends MockMvcWebConnectionBuilderSupport< } /** - * Create a new instance with the supplied {@link WebApplicationContext} - * and {@link MockMvcConfigurer}. + * Create a new {@code MockMvcWebClientBuilder} based on the supplied + * {@link WebApplicationContext} and {@link MockMvcConfigurer}. * @param context the {@code WebApplicationContext} to create a {@link MockMvc} * instance from; never {@code null} * @param configurer the MockMvcConfigurer to apply; never {@code null} @@ -71,38 +95,34 @@ public class MockMvcWebClientBuilder extends MockMvcWebConnectionBuilderSupport< } /** - * Create a new instance with the supplied {@link MockMvc} instance. - * @param mockMvc the {@code MockMvc} instance to use; never {@code null} - * @return the MockMvcWebClientBuilder to customize + * Supply the {@code WebClient} that the client {@linkplain #build built} + * by this builder should delegate to when processing + * non-{@linkplain WebRequestMatcher matching} requests. + * @param webClient the {@code WebClient} to delegate to for requests + * that do not match; never {@code null} + * @return this builder for further customization + * @see #build() */ - public static MockMvcWebClientBuilder mockMvcSetup(MockMvc mockMvc) { - Assert.notNull(mockMvc, "MockMvc must not be null"); - return new MockMvcWebClientBuilder(mockMvc); + public MockMvcWebClientBuilder withDelegate(WebClient webClient) { + Assert.notNull(webClient, "webClient must not be null"); + webClient.setWebConnection(createConnection(webClient.getWebConnection())); + this.webClient = webClient; + return this; } /** - * Create a {@link WebClient} that uses the configured {@link MockMvc} - * instance for any matching requests and a {@code WebClient} with all - * the default settings for any other requests. + * Build the {@link WebClient} configured via this builder. + *

The returned client will use the configured {@link MockMvc} instance + * for processing any {@linkplain WebRequestMatcher matching} requests + * and a delegate {@code WebClient} for all other requests. + *

If a {@linkplain #withDelegate delegate} has been explicitly configured, + * it will be used; otherwise, a default {@code WebClient} will be configured + * as the delegate. * @return the {@code WebClient} to use - * @see #configureWebClient(WebClient) + * @see #withDelegate(WebClient) */ - public WebClient createWebClient() { - return configureWebClient(new WebClient()); - } - - /** - * Configure the supplied {@link WebClient} to use the configured - * {@link MockMvc} instance for any matching requests and the supplied - * {@code WebClient} for any other requests. - * @param webClient the WebClient to delegate to for requests that do not - * match; never {@code null} - * @return the WebClient to use - */ - public WebClient configureWebClient(WebClient webClient) { - Assert.notNull(webClient, "webClient must not be null"); - webClient.setWebConnection(createConnection(webClient.getWebConnection())); - return webClient; + public WebClient build() { + return (this.webClient != null ? this.webClient : withDelegate(new WebClient()).build()); } } \ No newline at end of file diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebClientBuilderTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebClientBuilderTests.java index 5cf16c67591..ffee9a54ce6 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebClientBuilderTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebClientBuilderTests.java @@ -18,6 +18,7 @@ package org.springframework.test.web.servlet.htmlunit; import java.io.IOException; import java.net.URL; + import javax.servlet.http.HttpServletRequest; import org.junit.Before; @@ -42,14 +43,15 @@ import com.gargoylesoftware.htmlunit.WebClient; import com.gargoylesoftware.htmlunit.WebRequest; import com.gargoylesoftware.htmlunit.WebResponse; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.not; -import static org.junit.Assert.assertThat; +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.*; +import static org.springframework.test.web.servlet.htmlunit.MockMvcWebClientBuilder.*; /** * Integration tests for {@link MockMvcWebClientBuilder}. * * @author Rob Winch + * @author Sam Brannen * @since 4.2 */ @RunWith(SpringJUnit4ClassRunner.class) @@ -57,7 +59,7 @@ import static org.junit.Assert.assertThat; @WebAppConfiguration public class MockMvcWebClientBuilderTests { - private WebClient webClient = new WebClient(); + private WebClient webClient; @Autowired private WebApplicationContext wac; @@ -81,27 +83,20 @@ public class MockMvcWebClientBuilderTests { } @Test - public void mockMvcSetupAndConfigureWebClient() throws Exception { - Assume.group(TestGroup.PERFORMANCE); - - this.webClient = MockMvcWebClientBuilder - .mockMvcSetup(this.mockMvc) - .configureWebClient(this.webClient); + public void mockMvcSetupWithDefaultWebClientDelegate() throws Exception { + this.webClient = mockMvcSetup(this.mockMvc).build(); assertMvcProcessed("http://localhost/test"); - assertDelegateProcessed("http://example.com/"); + Assume.group(TestGroup.PERFORMANCE, () -> assertDelegateProcessed("http://example.com/")); } @Test - public void mockMvcSetupAndCreateWebClient() throws Exception { - Assume.group(TestGroup.PERFORMANCE); - - this.webClient = MockMvcWebClientBuilder - .mockMvcSetup(this.mockMvc) - .createWebClient(); + public void mockMvcSetupWithCustomWebClientDelegate() throws Exception { + WebClient preconfiguredWebClient = new WebClient(); + this.webClient = mockMvcSetup(this.mockMvc).withDelegate(preconfiguredWebClient).build(); assertMvcProcessed("http://localhost/test"); - assertDelegateProcessed("http://example.com/"); + Assume.group(TestGroup.PERFORMANCE, () -> assertDelegateProcessed("http://example.com/")); } private void assertMvcProcessed(String url) throws Exception { diff --git a/src/asciidoc/testing.adoc b/src/asciidoc/testing.adoc index 745432ac7fa..873957096f1 100644 --- a/src/asciidoc/testing.adoc +++ b/src/asciidoc/testing.adoc @@ -4344,7 +4344,7 @@ WebClient webClient; public void setup() { webClient = MockMvcWebClientBuilder .webAppContextSetup(context) - .createWebClient(); + .build(); } ---- @@ -4371,8 +4371,8 @@ HtmlPage createMsgFormPage = webClient.getPage("http://localhost/messages/form") [NOTE] ==== -The the context path is "". Alternatively, we could have specified the context path as -illustrated in <>. +The default context path is `""`. Alternatively, we could have specified the context +path as illustrated in <>. ==== We can then fill out the form and submit it to create a message. @@ -4430,7 +4430,7 @@ WebClient webClient; public void setup() { webClient = MockMvcWebClientBuilder .webAppContextSetup(context) - .createWebClient(); + .build(); } ---- @@ -4445,10 +4445,10 @@ public void setup() { .webAppContextSetup(context, springSecurity()) // for illustration only - defaults to "" .contextPath("") - // By default MockMvc is used for localhost only + // By default MockMvc is used for localhost only; // the following will use MockMvc for example.com and example.org too .useMockMvcForHosts("example.com","example.org") - .createWebClient(); + .build(); } ---- @@ -4465,15 +4465,14 @@ webClient = MockMvcWebClientBuilder .mockMvcSetup(mockMvc) // for illustration only - defaults to "" .contextPath("") - // By default MockMvc is used for localhost only + // By default MockMvc is used for localhost only; // the following will use MockMvc for example.com and example.org too .useMockMvcForHosts("example.com","example.org") - .createWebClient(); + .build(); ---- This is more verbose, but by building the `WebClient` with a `MockMvc` instance we have -the full power of `MockMvc` at our finger tips. Ultimately, this is simply performing the -following: +the full power of `MockMvc` at our finger tips. [TIP] ==== @@ -4738,7 +4737,7 @@ WebClient webClient; public void setup() { webClient = MockMvcWebClientBuilder .webAppContextSetup(context) - .createWebClient(); + .build(); } ---- @@ -4759,7 +4758,7 @@ public void setup() { // By default MockMvc is used for localhost only // the following will use MockMvc for example.com and example.org too .useMockMvcForHosts("example.com","example.org") - .createWebClient(); + .build(); } ---- @@ -4779,7 +4778,7 @@ webClient = MockMvcWebClientBuilder // By default MockMvc is used for localhost only // the following will use MockMvc for example.com and example.org too .useMockMvcForHosts("example.com","example.org") - .createWebClient(); + .build(); ---- This is more verbose, but by building the `WebDriver` with a `MockMvc` instance we have