Browse Source

MockHttpServletRequestBuilder parses form data

Spring MVC Test now parses application/x-www-form-urlencoded request
content and populates request parameters from it.

This can be useful when running client-side tests against a MockMvc
via MockMvcClientHttpRequestFactory.

Issue: SPR-13733
pull/942/head
Rossen Stoyanchev 10 years ago
parent
commit
415b2763ce
  1. 69
      spring-test/src/main/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilder.java
  2. 15
      spring-test/src/test/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilderTests.java
  3. 3
      src/asciidoc/whats-new.adoc

69
spring-test/src/main/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilder.java

@ -16,6 +16,9 @@ @@ -16,6 +16,9 @@
package org.springframework.test.web.servlet.request;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.security.Principal;
@ -33,8 +36,10 @@ import javax.servlet.http.Cookie; @@ -33,8 +36,10 @@ import javax.servlet.http.Cookie;
import org.springframework.beans.Mergeable;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.http.converter.FormHttpMessageConverter;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockHttpSession;
@ -603,24 +608,10 @@ public class MockHttpServletRequestBuilder @@ -603,24 +608,10 @@ public class MockHttpServletRequestBuilder
}
}
try {
if (this.url.getRawQuery() != null) {
request.setQueryString(this.url.getRawQuery());
}
MultiValueMap<String, String> queryParams =
UriComponentsBuilder.fromUri(this.url).build().getQueryParams();
for (Entry<String, List<String>> entry : queryParams.entrySet()) {
for (String value : entry.getValue()) {
value = (value != null) ? UriUtils.decode(value, "UTF-8") : null;
request.addParameter(UriUtils.decode(entry.getKey(), "UTF-8"), value);
}
}
}
catch (UnsupportedEncodingException ex) {
// shouldn't happen
if (this.url.getRawQuery() != null) {
request.setQueryString(this.url.getRawQuery());
}
addRequestParams(request, UriComponentsBuilder.fromUri(this.url).build().getQueryParams());
for (String name : this.parameters.keySet()) {
for (String value : this.parameters.get(name)) {
@ -632,6 +623,13 @@ public class MockHttpServletRequestBuilder @@ -632,6 +623,13 @@ public class MockHttpServletRequestBuilder
request.setContent(this.content);
request.setCharacterEncoding(this.characterEncoding);
if (this.content != null && this.contentType != null) {
MediaType mediaType = MediaType.parseMediaType(this.contentType);
if (MediaType.APPLICATION_FORM_URLENCODED.includes(mediaType)) {
addRequestParams(request, parseFormData(mediaType));
}
}
if (!ObjectUtils.isEmpty(this.cookies)) {
request.setCookies(this.cookies.toArray(new Cookie[this.cookies.size()]));
}
@ -695,6 +693,43 @@ public class MockHttpServletRequestBuilder @@ -695,6 +693,43 @@ public class MockHttpServletRequestBuilder
request.setPathInfo(this.pathInfo);
}
private void addRequestParams(MockHttpServletRequest request, MultiValueMap<String, String> map) {
try {
for (Entry<String, List<String>> entry : map.entrySet()) {
for (String value : entry.getValue()) {
value = (value != null) ? UriUtils.decode(value, "UTF-8") : null;
request.addParameter(UriUtils.decode(entry.getKey(), "UTF-8"), value);
}
}
}
catch (UnsupportedEncodingException ex) {
// shouldn't happen
}
}
private MultiValueMap<String, String> parseFormData(final MediaType mediaType) {
MultiValueMap<String, String> map;HttpInputMessage message = new HttpInputMessage() {
@Override
public InputStream getBody() throws IOException {
return new ByteArrayInputStream(content);
}
@Override
public HttpHeaders getHeaders() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(mediaType);
return headers;
}
};
try {
map = new FormHttpMessageConverter().read(null, message);
}
catch (IOException ex) {
throw new IllegalStateException("Failed to parse form data in request body: ", ex);
}
return map;
}
private FlashMapManager getFlashMapManager(MockHttpServletRequest request) {
FlashMapManager flashMapManager = null;
try {

15
spring-test/src/test/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilderTests.java

@ -18,6 +18,7 @@ package org.springframework.test.web.servlet.request; @@ -18,6 +18,7 @@ package org.springframework.test.web.servlet.request;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.Charset;
import java.security.Principal;
import java.util.Arrays;
import java.util.Collections;
@ -272,6 +273,20 @@ public class MockHttpServletRequestBuilderTests { @@ -272,6 +273,20 @@ public class MockHttpServletRequestBuilderTests {
assertArrayEquals(new String[] {"bar", "baz"}, request.getParameterMap().get("foo"));
}
@Test
public void requestParameterFromRequestBodyFormData() throws Exception {
String contentType = "application/x-www-form-urlencoded;charset=UTF-8";
String body = "name+1=value+1&name+2=value+A&name+2=value+B&name+3";
MockHttpServletRequest request = new MockHttpServletRequestBuilder(HttpMethod.POST, "/foo")
.contentType(contentType).content(body.getBytes(Charset.forName("UTF-8")))
.buildRequest(this.servletContext);
assertArrayEquals(new String[] {"value 1"}, request.getParameterMap().get("name 1"));
assertArrayEquals(new String[] {"value A", "value B"}, request.getParameterMap().get("name 2"));
assertArrayEquals(new String[] {null}, request.getParameterMap().get("name 3"));
}
@Test
public void acceptHeader() {
this.builder.accept(MediaType.TEXT_HTML, MediaType.APPLICATION_XML);

3
src/asciidoc/whats-new.adoc

@ -672,5 +672,6 @@ Spring 4.3 also improves the caching abstraction as follows: @@ -672,5 +672,6 @@ Spring 4.3 also improves the caching abstraction as follows:
=== Testing Improvements
* The JUnit support in the _Spring TestContext Framework_ now requires JUnit 4.12 or higher.
* Server-side Spring MVC Test supports expectations on response headers with multiple values.
* Server-side Spring MVC Test parses form data request content and populates request parameters.
* Client-side Spring MVC Test supports expectations for form data in the request body.
* Server-side Spring MVC Test supports expectations on response headers with multiple values.
Loading…
Cancel
Save