From 7d96ad1f6ece5534092ff537d9f89f914a9c2566 Mon Sep 17 00:00:00 2001 From: Rob Winch Date: Fri, 18 Mar 2016 09:09:17 -0500 Subject: [PATCH] MockMvc HtmlUnit support shares CookieManager Previously MockMvc builders failed to share the WebConnection used for managing cookies in the MockMvcWebConnection. This meant that the various CookieManagers would have different states. This commit ensures that the WebConnection is set on the MockMvcWebConnection. Fixes SPR-14066 --- .../htmlunit/MockMvcWebClientBuilder.java | 2 +- .../htmlunit/MockMvcWebConnection.java | 44 +++++++++-- .../MockMvcWebConnectionBuilderSupport.java | 40 +++++++++- .../MockMvcHtmlUnitDriverBuilder.java | 2 +- .../WebConnectionHtmlUnitDriver.java | 8 +- .../MockMvcConnectionBuilderSupportTests.java | 77 +++++++++++++++++-- .../MockMvcWebClientBuilderTests.java | 20 +++++ .../htmlunit/MockMvcWebConnectionTests.java | 3 +- .../MockMvcHtmlUnitDriverBuilderTests.java | 24 ++++++ 9 files changed, 199 insertions(+), 21 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 5dc12a2118..94cc1ea865 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 @@ -106,7 +106,7 @@ public class MockMvcWebClientBuilder extends MockMvcWebConnectionBuilderSupport< */ public MockMvcWebClientBuilder withDelegate(WebClient webClient) { Assert.notNull(webClient, "WebClient must not be null"); - webClient.setWebConnection(createConnection(webClient.getWebConnection())); + webClient.setWebConnection(createConnection(webClient)); this.webClient = webClient; return this; } diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebConnection.java b/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebConnection.java index d7a6fe6087..184d0b7ec7 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebConnection.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebConnection.java @@ -63,6 +63,38 @@ public final class MockMvcWebConnection implements WebConnection { private WebClient webClient; + /** + * Create a new instance that assumes the context path of the application + * is {@code ""} (i.e., the root context). + *

For example, the URL {@code http://localhost/test/this} would use + * {@code ""} as the context path. + * @param mockMvc the {@code MockMvc} instance to use; never {@code null} + * @param webClient the {@link WebClient} to use. never {@code null} + */ + public MockMvcWebConnection(MockMvc mockMvc, WebClient webClient) { + this(mockMvc, webClient, ""); + } + + /** + * Create a new instance with the specified context path. + *

The path may be {@code null} in which case the first path segment + * of the URL is turned into the contextPath. Otherwise it must conform + * to {@link javax.servlet.http.HttpServletRequest#getContextPath()} + * which states that it can be an empty string and otherwise must start + * with a "/" character and not end with a "/" character. + * @param mockMvc the {@code MockMvc} instance to use; never {@code null} + * @param webClient the {@link WebClient} to use. never {@code null} + * @param contextPath the contextPath to use + */ + public MockMvcWebConnection(MockMvc mockMvc, WebClient webClient, String contextPath) { + Assert.notNull(mockMvc, "MockMvc must not be null"); + Assert.notNull(webClient, "WebClient must not be null"); + validateContextPath(contextPath); + + this.webClient = webClient; + this.mockMvc = mockMvc; + this.contextPath = contextPath; + } /** * Create a new instance that assumes the context path of the application @@ -70,7 +102,9 @@ public final class MockMvcWebConnection implements WebConnection { *

For example, the URL {@code http://localhost/test/this} would use * {@code ""} as the context path. * @param mockMvc the {@code MockMvc} instance to use; never {@code null} + * @deprecated Use {@link #MockMvcWebConnection(MockMvc, WebClient)} */ + @Deprecated public MockMvcWebConnection(MockMvc mockMvc) { this(mockMvc, ""); } @@ -84,17 +118,13 @@ public final class MockMvcWebConnection implements WebConnection { * with a "/" character and not end with a "/" character. * @param mockMvc the {@code MockMvc} instance to use; never {@code null} * @param contextPath the contextPath to use + * @deprecated use {@link #MockMvcWebConnection(MockMvc, WebClient, String)} */ + @Deprecated public MockMvcWebConnection(MockMvc mockMvc, String contextPath) { - Assert.notNull(mockMvc, "MockMvc must not be null"); - validateContextPath(contextPath); - - this.webClient = new WebClient(); - this.mockMvc = mockMvc; - this.contextPath = contextPath; + this(mockMvc, new WebClient(), contextPath); } - public void setWebClient(WebClient webClient) { Assert.notNull(webClient, "WebClient must not be null"); this.webClient = webClient; diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebConnectionBuilderSupport.java b/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebConnectionBuilderSupport.java index 6575e6a26e..d60d2d4d1b 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebConnectionBuilderSupport.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebConnectionBuilderSupport.java @@ -19,6 +19,7 @@ package org.springframework.test.web.servlet.htmlunit; import java.util.ArrayList; import java.util.List; +import com.gargoylesoftware.htmlunit.WebClient; import com.gargoylesoftware.htmlunit.WebConnection; import org.springframework.test.web.servlet.MockMvc; @@ -145,10 +146,46 @@ public abstract class MockMvcWebConnectionBuilderSupport assertDelegateProcessed("http://example.com/")); } + // SPR-14066 + @Test + public void cookieManagerShared() throws Exception { + this.mockMvc = MockMvcBuilders.standaloneSetup(new CookieController()).build(); + this.webClient = mockMvcSetup(this.mockMvc).build(); + + assertThat(getWebResponse("http://localhost/").getContentAsString(), equalTo("")); + this.webClient.getCookieManager().addCookie(new Cookie("localhost", "cookie", "cookieManagerShared")); + assertThat(getWebResponse("http://localhost/").getContentAsString(), equalTo("cookieManagerShared")); + } + private void assertMvcProcessed(String url) throws Exception { assertThat(getWebResponse(url).getContentAsString(), equalTo("mvc")); } @@ -126,4 +139,11 @@ public class MockMvcWebClientBuilderTests { } } + @RestController + static class CookieController { + @RequestMapping("/") + public String cookie(@CookieValue("cookie") String cookie) { + return cookie; + } + } } diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebConnectionTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebConnectionTests.java index 726c4f0bb6..78e207b2e1 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebConnectionTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebConnectionTests.java @@ -36,6 +36,7 @@ import static org.junit.Assert.assertThat; * @author Rob Winch * @since 4.2 */ +@SuppressWarnings("deprecation") public class MockMvcWebConnectionTests { private final WebClient webClient = new WebClient(); @@ -50,7 +51,7 @@ public class MockMvcWebConnectionTests { @Test public void contextPathNull() throws IOException { - this.webClient.setWebConnection(new MockMvcWebConnection(this.mockMvc, null)); + this.webClient.setWebConnection(new MockMvcWebConnection(this.mockMvc, (String) null)); Page page = this.webClient.getPage("http://localhost/context/a"); diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/webdriver/MockMvcHtmlUnitDriverBuilderTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/webdriver/MockMvcHtmlUnitDriverBuilderTests.java index 9fe37224bc..3a1bf27a37 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/webdriver/MockMvcHtmlUnitDriverBuilderTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/webdriver/MockMvcHtmlUnitDriverBuilderTests.java @@ -35,11 +35,14 @@ import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.tests.Assume; import org.springframework.tests.TestGroup; +import org.springframework.web.bind.annotation.CookieValue; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import com.gargoylesoftware.htmlunit.util.Cookie; + import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; import static org.springframework.test.web.servlet.htmlunit.webdriver.MockMvcHtmlUnitDriverBuilder.*; @@ -111,6 +114,20 @@ public class MockMvcHtmlUnitDriverBuilderTests { assertFalse(this.driver.isJavascriptEnabled()); } + // SPR-14066 + @Test + public void cookieManagerShared() throws Exception { + WebConnectionHtmlUnitDriver delegateDriver = new WebConnectionHtmlUnitDriver(); + this.mockMvc = MockMvcBuilders.standaloneSetup(new CookieController()).build(); + this.driver = mockMvcSetup(this.mockMvc) + .withDelegate(delegateDriver) + .build(); + + assertThat(get("http://localhost/"), equalTo("")); + delegateDriver.getWebClient().getCookieManager().addCookie(new Cookie("localhost", "cookie", "cookieManagerShared")); + assertThat(get("http://localhost/"), equalTo("cookieManagerShared")); + } + private void assertMvcProcessed(String url) throws Exception { assertThat(get(url), containsString(EXPECTED_BODY)); } @@ -139,4 +156,11 @@ public class MockMvcHtmlUnitDriverBuilderTests { } } + @RestController + static class CookieController { + @RequestMapping("/") + public String cookie(@CookieValue("cookie") String cookie) { + return cookie; + } + } } \ No newline at end of file