提交 415b2763 编写于 作者: R Rossen Stoyanchev

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
上级 6a9455b7
......@@ -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;
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
}
}
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
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
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 {
......
......@@ -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 {
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);
......
......@@ -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.
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册