From 3b84a7e84d0a48a5efde12b04348d21c29fa1eaf Mon Sep 17 00:00:00 2001 From: Sam Brannen Date: Mon, 27 Jul 2015 19:27:15 +0200 Subject: [PATCH] Redesign MockMvcWebClientBuilder API This commit introduces a dedicated build() method in MockMvcWebClientBuilder to replace createWebClient(). In addition, the configureWebClient() method has been renamed to withDelegate() and now returns the builder for further customization. This commit also overhauls the constructor and class-level Javadoc in MockMvcWebClientBuilder for greater clarity to end users. Issues SPR-13158 --- .../htmlunit/MockMvcWebClientBuilder.java | 82 ++++++++++++------- .../MockMvcWebClientBuilderTests.java | 31 +++---- src/asciidoc/testing.adoc | 25 +++--- 3 files changed, 76 insertions(+), 62 deletions(-) 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