From 879b2df052d64eb552fccbf9c82195fb134c7783 Mon Sep 17 00:00:00 2001 From: Johannes Teklote Date: Tue, 12 Nov 2019 14:31:42 +0100 Subject: [PATCH] queryParam options for MockMVC requeusts See gh-23296 --- .../MockHttpServletRequestBuilder.java | 51 ++++++++++++++++++- .../MockHttpServletRequestBuilderTests.java | 42 +++++++++++++++ 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilder.java b/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilder.java index 9b6cf1c8fde..d88acf31f2d 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilder.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilder.java @@ -28,6 +28,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.stream.Collectors; import javax.servlet.ServletContext; import javax.servlet.ServletRequest; @@ -100,6 +101,9 @@ public class MockHttpServletRequestBuilder @Nullable private Boolean secure; + @Nullable + private String queryString = ""; + @Nullable private Principal principal; @@ -354,6 +358,40 @@ public class MockHttpServletRequestBuilder return this; } + /** + * Add a query parameter to the {@link MockHttpServletRequest}. + *

If called more than once, new values get added to existing ones. + * @param name the parameter name + * @param values one or more values + */ + public MockHttpServletRequestBuilder queryParam(String name, String... values) { + param(name, values); + String builder = Arrays.stream(values).map(value -> UriUtils.encode(name, StandardCharsets.UTF_8) + + ((value != null) ? ("=" + UriUtils.encode(value, StandardCharsets.UTF_8)) : "") + "&" + ).collect(Collectors.joining()); + queryString += builder; + return this; + } + + /** + * Add a map of query parameters to the {@link MockHttpServletRequest}, + * for example when testing a form submission. + *

If called more than once, new values get added to existing ones. + * @param params the parameters to add + * @since 4.2.4 + */ + public MockHttpServletRequestBuilder queryParams(MultiValueMap params) { + params(params); + StringBuilder builder = new StringBuilder(); + params.forEach((key, values) -> values.forEach(value -> { + builder.append(UriUtils.encode(key, StandardCharsets.UTF_8)) + .append(((value != null) ? ("=" + UriUtils.encode(value, StandardCharsets.UTF_8)) : "")) + .append("&"); + })); + queryString += builder.toString(); + return this; + } + /** * Add the given cookies to the request. Cookies are always added. * @param cookies the cookies to add @@ -636,13 +674,24 @@ public class MockHttpServletRequestBuilder request.setQueryString(this.url.getRawQuery()); } addRequestParams(request, UriComponentsBuilder.fromUri(this.url).build().getQueryParams()); - this.parameters.forEach((name, values) -> { for (String value : values) { request.addParameter(name, value); } }); + StringBuilder queryBuilder = new StringBuilder(); + if (request.getQueryString() != null) { + queryBuilder.append(request.getQueryString()); + } + if (this.queryString != null && !"".equals(this.queryString)) { + if (queryBuilder.length() > 0) { + queryBuilder.append("&"); + } + queryBuilder.append(this.queryString, 0, this.queryString.length() - 1); + request.setQueryString(queryBuilder.toString()); + } + if (this.content != null && this.content.length > 0) { String requestContentType = request.getContentType(); if (requestContentType != null) { diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilderTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilderTests.java index 22362a33d16..34c29ce4b3c 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilderTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/request/MockHttpServletRequestBuilderTests.java @@ -21,6 +21,7 @@ import java.net.URI; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; import java.security.Principal; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; @@ -234,6 +235,47 @@ public class MockHttpServletRequestBuilderTests { assertThat(request.getParameter("foo[1]")).isEqualTo("baz"); } + @Test + public void requestParameterToQuery() { + this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/"); + this.builder.queryParam("foo", "bar"); + this.builder.queryParam("foo", "baz"); + + MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); + + assertThat(request.getParameterMap().get("foo")).isEqualTo(new String[] {"bar", "baz"}); + assertThat(request.getQueryString()).isEqualTo("foo=bar&foo=baz"); + } + + @Test + public void requestParameterMapToQuery() { + this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/"); + MultiValueMap queryParams = new LinkedMultiValueMap<>(); + List values = new ArrayList<>(); + values.add("bar"); + values.add("baz"); + queryParams.put("foo", values); + this.builder.queryParams(queryParams); + + MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); + + assertThat(request.getParameterMap().get("foo")).isEqualTo(new String[] {"bar", "baz"}); + assertThat(request.getQueryString()).isEqualTo("foo=bar&foo=baz"); + } + + @Test + public void requestParameterToQueryList() { + this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/"); + this.builder.queryParam("foo[0]", "bar"); + this.builder.queryParam("foo[1]", "baz"); + + MockHttpServletRequest request = this.builder.buildRequest(this.servletContext); + + assertThat(request.getQueryString()).isEqualTo("foo%5B0%5D=bar&foo%5B1%5D=baz"); + assertThat(request.getParameter("foo[0]")).isEqualTo("bar"); + assertThat(request.getParameter("foo[1]")).isEqualTo("baz"); + } + @Test public void requestParameterFromQueryWithEncoding() { this.builder = new MockHttpServletRequestBuilder(HttpMethod.GET, "/?foo={value}", "bar=baz");