Browse Source

Merge pull request #1055 from rwinch/SPR-14265

pull/1070/head
Rossen Stoyanchev 9 years ago
parent
commit
e2fa282e14
  1. 66
      spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebConnection.java
  2. 7
      spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/MockWebResponseBuilder.java
  3. 50
      spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebClientBuilderTests.java

66
spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebConnection.java

@ -17,13 +17,16 @@ @@ -17,13 +17,16 @@
package org.springframework.test.web.servlet.htmlunit;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.gargoylesoftware.htmlunit.CookieManager;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebConnection;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.WebResponse;
import com.gargoylesoftware.htmlunit.util.Cookie;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockHttpSession;
@ -62,6 +65,7 @@ public final class MockMvcWebConnection implements WebConnection { @@ -62,6 +65,7 @@ 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).
@ -124,6 +128,27 @@ public final class MockMvcWebConnection implements WebConnection { @@ -124,6 +128,27 @@ public final class MockMvcWebConnection implements WebConnection {
this(mockMvc, new WebClient(), contextPath);
}
/**
* Validate the supplied {@code contextPath}.
* <p>If the value is not {@code null}, 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 contextPath the path to validate
*/
static void validateContextPath(String contextPath) {
if (contextPath == null || "".equals(contextPath)) {
return;
}
if (!contextPath.startsWith("/")) {
throw new IllegalArgumentException("contextPath '" + contextPath + "' must start with '/'.");
}
if (contextPath.endsWith("/")) {
throw new IllegalArgumentException("contextPath '" + contextPath + "' must not end with '/'.");
}
}
public void setWebClient(WebClient webClient) {
Assert.notNull(webClient, "WebClient must not be null");
this.webClient = webClient;
@ -142,6 +167,7 @@ public final class MockMvcWebConnection implements WebConnection { @@ -142,6 +167,7 @@ public final class MockMvcWebConnection implements WebConnection {
httpServletResponse = getResponse(requestBuilder);
forwardedUrl = httpServletResponse.getForwardedUrl();
}
storeCookies(webRequest, httpServletResponse.getCookies());
return new MockWebResponseBuilder(startTime, webRequest, httpServletResponse).build();
}
@ -158,29 +184,29 @@ public final class MockMvcWebConnection implements WebConnection { @@ -158,29 +184,29 @@ public final class MockMvcWebConnection implements WebConnection {
return resultActions.andReturn().getResponse();
}
@Override
public void close() {
}
/**
* Validate the supplied {@code contextPath}.
* <p>If the value is not {@code null}, 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 contextPath the path to validate
*/
static void validateContextPath(String contextPath) {
if (contextPath == null || "".equals(contextPath)) {
private void storeCookies(WebRequest webRequest, javax.servlet.http.Cookie[] cookies) {
if (cookies == null) {
return;
}
if (!contextPath.startsWith("/")) {
throw new IllegalArgumentException("contextPath '" + contextPath + "' must start with '/'.");
}
if (contextPath.endsWith("/")) {
throw new IllegalArgumentException("contextPath '" + contextPath + "' must not end with '/'.");
Date now = new Date();
CookieManager cookieManager = this.webClient.getCookieManager();
for (javax.servlet.http.Cookie cookie : cookies) {
if (cookie.getDomain() == null) {
cookie.setDomain(webRequest.getUrl().getHost());
}
Cookie toManage = MockWebResponseBuilder.createCookie(cookie);
Date expires = toManage.getExpires();
if (expires == null || expires.after(now)) {
cookieManager.addCookie(toManage);
}
else {
cookieManager.removeCookie(toManage);
}
}
}
@Override
public void close() {
}
}

7
spring-test/src/main/java/org/springframework/test/web/servlet/htmlunit/MockWebResponseBuilder.java

@ -112,6 +112,10 @@ final class MockWebResponseBuilder { @@ -112,6 +112,10 @@ final class MockWebResponseBuilder {
}
private String valueOfCookie(Cookie cookie) {
return createCookie(cookie).toString();
}
static com.gargoylesoftware.htmlunit.util.Cookie createCookie(Cookie cookie) {
Date expires = null;
if (cookie.getMaxAge() > -1) {
expires = new Date(System.currentTimeMillis() + cookie.getMaxAge() * 1000);
@ -125,7 +129,6 @@ final class MockWebResponseBuilder { @@ -125,7 +129,6 @@ final class MockWebResponseBuilder {
if(cookie.isHttpOnly()) {
result.setAttribute("httponly", "true");
}
return new com.gargoylesoftware.htmlunit.util.Cookie(result).toString();
return new com.gargoylesoftware.htmlunit.util.Cookie(result);
}
}

50
spring-test/src/test/java/org/springframework/test/web/servlet/htmlunit/MockMvcWebClientBuilderTests.java

@ -19,7 +19,9 @@ package org.springframework.test.web.servlet.htmlunit; @@ -19,7 +19,9 @@ package org.springframework.test.web.servlet.htmlunit;
import java.io.IOException;
import java.net.URL;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.gargoylesoftware.htmlunit.HttpMethod;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.WebRequest;
import com.gargoylesoftware.htmlunit.WebResponse;
@ -38,7 +40,10 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; @@ -38,7 +40,10 @@ 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.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
@ -103,11 +108,22 @@ public class MockMvcWebClientBuilderTests { @@ -103,11 +108,22 @@ public class MockMvcWebClientBuilderTests {
this.mockMvc = MockMvcBuilders.standaloneSetup(new CookieController()).build();
WebClient client = MockMvcWebClientBuilder.mockMvcSetup(this.mockMvc).build();
assertThat(getResponse(client, "http://localhost/").getContentAsString(), equalTo(""));
assertThat(getResponse(client, "http://localhost/").getContentAsString(), equalTo("NA"));
client.getCookieManager().addCookie(new Cookie("localhost", "cookie", "cookieManagerShared"));
assertThat(getResponse(client, "http://localhost/").getContentAsString(), equalTo("cookieManagerShared"));
}
@Test // SPR-14265
public void cookiesAreManaged() throws Exception {
this.mockMvc = MockMvcBuilders.standaloneSetup(new CookieController()).build();
WebClient client = MockMvcWebClientBuilder.mockMvcSetup(this.mockMvc).build();
assertThat(getResponse(client, "http://localhost/").getContentAsString(), equalTo("NA"));
assertThat(postResponse(client, "http://localhost/?cookie=foo").getContentAsString(), equalTo("Set"));
assertThat(getResponse(client, "http://localhost/").getContentAsString(), equalTo("foo"));
assertThat(deleteResponse(client, "http://localhost/").getContentAsString(), equalTo("Delete"));
assertThat(getResponse(client, "http://localhost/").getContentAsString(), equalTo("NA"));
}
private void assertMockMvcUsed(WebClient client, String url) throws Exception {
assertThat(getResponse(client, url).getContentAsString(), equalTo("mvc"));
@ -118,7 +134,19 @@ public class MockMvcWebClientBuilderTests { @@ -118,7 +134,19 @@ public class MockMvcWebClientBuilderTests {
}
private WebResponse getResponse(WebClient client, String url) throws IOException {
return client.getWebConnection().getResponse(new WebRequest(new URL(url)));
return createResponse(client, new WebRequest(new URL(url)));
}
private WebResponse postResponse(WebClient client, String url) throws IOException {
return createResponse(client, new WebRequest(new URL(url), HttpMethod.POST));
}
private WebResponse deleteResponse(WebClient client, String url) throws IOException {
return createResponse(client, new WebRequest(new URL(url), HttpMethod.DELETE));
}
private WebResponse createResponse(WebClient client, WebRequest request) throws IOException {
return client.getWebConnection().getResponse(request);
}
@ -139,10 +167,26 @@ public class MockMvcWebClientBuilderTests { @@ -139,10 +167,26 @@ public class MockMvcWebClientBuilderTests {
@RestController
static class CookieController {
static final String COOKIE_NAME = "cookie";
@RequestMapping(path = "/", produces = "text/plain")
String cookie(@CookieValue("cookie") String cookie) {
String cookie(@CookieValue(name = COOKIE_NAME, defaultValue = "NA") String cookie) {
return cookie;
}
@PostMapping(path = "/", produces = "text/plain")
String setCookie(@RequestParam String cookie, HttpServletResponse response) {
response.addCookie(new javax.servlet.http.Cookie(COOKIE_NAME, cookie));
return "Set";
}
@DeleteMapping(path = "/", produces = "text/plain")
String deleteCookie(HttpServletResponse response) {
javax.servlet.http.Cookie cookie = new javax.servlet.http.Cookie(COOKIE_NAME, "");
cookie.setMaxAge(0);
response.addCookie(cookie);
return "Delete";
}
}
}

Loading…
Cancel
Save