diff --git a/spring-test/src/main/java/org/springframework/mock/http/server/reactive/MockServerHttpRequest.java b/spring-test/src/main/java/org/springframework/mock/http/server/reactive/MockServerHttpRequest.java
index 25889ec448..e37aa40b10 100644
--- a/spring-test/src/main/java/org/springframework/mock/http/server/reactive/MockServerHttpRequest.java
+++ b/spring-test/src/main/java/org/springframework/mock/http/server/reactive/MockServerHttpRequest.java
@@ -133,6 +133,8 @@ public class MockServerHttpRequest extends AbstractServerHttpRequest {
/**
* Alternative to {@link #method(HttpMethod, URI)} that accepts a URI template.
+ * The given URI may contain query parameters, or those may be added later via
+ * {@link BaseBuilder#queryParam queryParam} builder methods.
* @param method the HTTP method (GET, POST, etc)
* @param urlTemplate the URL template
* @param vars variables to expand into the template
@@ -144,7 +146,9 @@ public class MockServerHttpRequest extends AbstractServerHttpRequest {
}
/**
- * Create an HTTP GET builder with the given url.
+ * Create an HTTP GET builder with the given URI template. The given URI may
+ * contain query parameters, or those may be added later via
+ * {@link BaseBuilder#queryParam queryParam} builder methods.
* @param urlTemplate a URL template; the resulting URL will be encoded
* @param uriVars zero or more URI variables
* @return the created builder
@@ -154,7 +158,7 @@ public class MockServerHttpRequest extends AbstractServerHttpRequest {
}
/**
- * Create an HTTP HEAD builder with the given url.
+ * HTTP HEAD variant. See {@link #get(String, Object...)} for general info.
* @param urlTemplate a URL template; the resulting URL will be encoded
* @param uriVars zero or more URI variables
* @return the created builder
@@ -164,7 +168,7 @@ public class MockServerHttpRequest extends AbstractServerHttpRequest {
}
/**
- * Create an HTTP POST builder with the given url.
+ * HTTP POST variant. See {@link #get(String, Object...)} for general info.
* @param urlTemplate a URL template; the resulting URL will be encoded
* @param uriVars zero or more URI variables
* @return the created builder
@@ -174,7 +178,8 @@ public class MockServerHttpRequest extends AbstractServerHttpRequest {
}
/**
- * Create an HTTP PUT builder with the given url.
+ * HTTP PUT variant. See {@link #get(String, Object...)} for general info.
+ * {@link BaseBuilder#queryParam queryParam} builder methods.
* @param urlTemplate a URL template; the resulting URL will be encoded
* @param uriVars zero or more URI variables
* @return the created builder
@@ -184,7 +189,7 @@ public class MockServerHttpRequest extends AbstractServerHttpRequest {
}
/**
- * Create an HTTP PATCH builder with the given url.
+ * HTTP PATCH variant. See {@link #get(String, Object...)} for general info.
* @param urlTemplate a URL template; the resulting URL will be encoded
* @param uriVars zero or more URI variables
* @return the created builder
@@ -194,7 +199,7 @@ public class MockServerHttpRequest extends AbstractServerHttpRequest {
}
/**
- * Create an HTTP DELETE builder with the given url.
+ * HTTP DELETE variant. See {@link #get(String, Object...)} for general info.
* @param urlTemplate a URL template; the resulting URL will be encoded
* @param uriVars zero or more URI variables
* @return the created builder
@@ -204,7 +209,7 @@ public class MockServerHttpRequest extends AbstractServerHttpRequest {
}
/**
- * Creates an HTTP OPTIONS builder with the given url.
+ * HTTP OPTIONS variant. See {@link #get(String, Object...)} for general info.
* @param urlTemplate a URL template; the resulting URL will be encoded
* @param uriVars zero or more URI variables
* @return the created builder
@@ -225,6 +230,25 @@ public class MockServerHttpRequest extends AbstractServerHttpRequest {
*/
B contextPath(String contextPath);
+ /**
+ * Append the given query parameter to the existing query parameters.
+ * If no values are given, the resulting URI will contain the query
+ * parameter name only (i.e. {@code ?foo} instead of {@code ?foo=bar}).
+ *
The provided query name and values will be encoded.
+ * @param name the query parameter name
+ * @param values the query parameter values
+ * @return this UriComponentsBuilder
+ */
+ B queryParam(String name, Object... values);
+
+ /**
+ * Add the given query parameters and values. The provided query name
+ * and corresponding values will be encoded.
+ * @param params the params
+ * @return this UriComponentsBuilder
+ */
+ B queryParams(MultiValueMap params);
+
/**
* Set the remote address to return.
*/
@@ -375,6 +399,8 @@ public class MockServerHttpRequest extends AbstractServerHttpRequest {
@Nullable
private String contextPath;
+ private final UriComponentsBuilder queryParamsBuilder = UriComponentsBuilder.newInstance();
+
private final HttpHeaders headers = new HttpHeaders();
private final MultiValueMap cookies = new LinkedMultiValueMap<>();
@@ -397,6 +423,18 @@ public class MockServerHttpRequest extends AbstractServerHttpRequest {
return this;
}
+ @Override
+ public BodyBuilder queryParam(String name, Object... values) {
+ this.queryParamsBuilder.queryParam(name, values);
+ return this;
+ }
+
+ @Override
+ public BodyBuilder queryParams(MultiValueMap params) {
+ this.queryParamsBuilder.queryParams(params);
+ return this;
+ }
+
@Override
public BodyBuilder remoteAddress(InetSocketAddress remoteAddress) {
this.remoteAddress = remoteAddress;
@@ -506,7 +544,7 @@ public class MockServerHttpRequest extends AbstractServerHttpRequest {
@Override
public MockServerHttpRequest body(Publisher extends DataBuffer> body) {
applyCookiesIfNecessary();
- return new MockServerHttpRequest(this.method, this.url, this.contextPath,
+ return new MockServerHttpRequest(this.method, getUrlToUse(), this.contextPath,
this.headers, this.cookies, this.remoteAddress, this.sslInfo, body);
}
@@ -516,6 +554,17 @@ public class MockServerHttpRequest extends AbstractServerHttpRequest {
.forEach(cookie -> this.headers.add(HttpHeaders.COOKIE, cookie.toString()));
}
}
+
+ private URI getUrlToUse() {
+ MultiValueMap params =
+ this.queryParamsBuilder.buildAndExpand().encode().getQueryParams();
+
+ if (!params.isEmpty()) {
+ return UriComponentsBuilder.fromUri(this.url).queryParams(params).build(true).toUri();
+ }
+
+ return this.url;
+ }
}
}
\ No newline at end of file
diff --git a/spring-test/src/test/java/org/springframework/mock/http/server/reactive/MockServerHttpRequestTests.java b/spring-test/src/test/java/org/springframework/mock/http/server/reactive/MockServerHttpRequestTests.java
index dc8f6e148b..c7ecb6e350 100644
--- a/spring-test/src/test/java/org/springframework/mock/http/server/reactive/MockServerHttpRequestTests.java
+++ b/spring-test/src/test/java/org/springframework/mock/http/server/reactive/MockServerHttpRequestTests.java
@@ -30,7 +30,6 @@ import static org.junit.Assert.assertEquals;
*/
public class MockServerHttpRequestTests {
-
@Test
public void cookieHeaderSet() throws Exception {
HttpCookie foo11 = new HttpCookie("foo1", "bar1");
@@ -47,4 +46,15 @@ public class MockServerHttpRequestTests {
request.getHeaders().get(HttpHeaders.COOKIE));
}
+ @Test
+ public void queryParams() throws Exception {
+ MockServerHttpRequest request = MockServerHttpRequest.get("/foo bar?a=b")
+ .queryParam("name A", "value A1", "value A2")
+ .queryParam("name B", "value B1")
+ .build();
+
+ assertEquals("/foo%20bar?a=b&name%20A=value%20A1&name%20A=value%20A2&name%20B=value%20B1",
+ request.getURI().toString());
+ }
+
}
diff --git a/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java b/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java
index 6ab0892cd8..0f92c40c02 100644
--- a/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java
+++ b/spring-web/src/main/java/org/springframework/web/util/UriComponentsBuilder.java
@@ -632,7 +632,7 @@ public class UriComponentsBuilder implements UriBuilder, Cloneable {
* Append the given query parameter to the existing query parameters. The
* given name or any of the values may contain URI template variables. If no
* values are given, the resulting URI will contain the query parameter name
- * only (i.e. {@code ?foo} instead of {@code ?foo=bar}.
+ * only (i.e. {@code ?foo} instead of {@code ?foo=bar}).
* @param name the query parameter name
* @param values the query parameter values
* @return this UriComponentsBuilder
diff --git a/spring-web/src/test/java/org/springframework/mock/http/server/reactive/test/MockServerHttpRequest.java b/spring-web/src/test/java/org/springframework/mock/http/server/reactive/test/MockServerHttpRequest.java
index ffe448ec23..ed4e9b8311 100644
--- a/spring-web/src/test/java/org/springframework/mock/http/server/reactive/test/MockServerHttpRequest.java
+++ b/spring-web/src/test/java/org/springframework/mock/http/server/reactive/test/MockServerHttpRequest.java
@@ -133,6 +133,8 @@ public class MockServerHttpRequest extends AbstractServerHttpRequest {
/**
* Alternative to {@link #method(HttpMethod, URI)} that accepts a URI template.
+ * The given URI may contain query parameters, or those may be added later via
+ * {@link BaseBuilder#queryParam queryParam} builder methods.
* @param method the HTTP method (GET, POST, etc)
* @param urlTemplate the URL template
* @param vars variables to expand into the template
@@ -144,7 +146,9 @@ public class MockServerHttpRequest extends AbstractServerHttpRequest {
}
/**
- * Create an HTTP GET builder with the given url.
+ * Create an HTTP GET builder with the given URI template. The given URI may
+ * contain query parameters, or those may be added later via
+ * {@link BaseBuilder#queryParam queryParam} builder methods.
* @param urlTemplate a URL template; the resulting URL will be encoded
* @param uriVars zero or more URI variables
* @return the created builder
@@ -154,7 +158,7 @@ public class MockServerHttpRequest extends AbstractServerHttpRequest {
}
/**
- * Create an HTTP HEAD builder with the given url.
+ * HTTP HEAD variant. See {@link #get(String, Object...)} for general info.
* @param urlTemplate a URL template; the resulting URL will be encoded
* @param uriVars zero or more URI variables
* @return the created builder
@@ -164,7 +168,7 @@ public class MockServerHttpRequest extends AbstractServerHttpRequest {
}
/**
- * Create an HTTP POST builder with the given url.
+ * HTTP POST variant. See {@link #get(String, Object...)} for general info.
* @param urlTemplate a URL template; the resulting URL will be encoded
* @param uriVars zero or more URI variables
* @return the created builder
@@ -174,7 +178,8 @@ public class MockServerHttpRequest extends AbstractServerHttpRequest {
}
/**
- * Create an HTTP PUT builder with the given url.
+ * HTTP PUT variant. See {@link #get(String, Object...)} for general info.
+ * {@link BaseBuilder#queryParam queryParam} builder methods.
* @param urlTemplate a URL template; the resulting URL will be encoded
* @param uriVars zero or more URI variables
* @return the created builder
@@ -184,7 +189,7 @@ public class MockServerHttpRequest extends AbstractServerHttpRequest {
}
/**
- * Create an HTTP PATCH builder with the given url.
+ * HTTP PATCH variant. See {@link #get(String, Object...)} for general info.
* @param urlTemplate a URL template; the resulting URL will be encoded
* @param uriVars zero or more URI variables
* @return the created builder
@@ -194,7 +199,7 @@ public class MockServerHttpRequest extends AbstractServerHttpRequest {
}
/**
- * Create an HTTP DELETE builder with the given url.
+ * HTTP DELETE variant. See {@link #get(String, Object...)} for general info.
* @param urlTemplate a URL template; the resulting URL will be encoded
* @param uriVars zero or more URI variables
* @return the created builder
@@ -204,7 +209,7 @@ public class MockServerHttpRequest extends AbstractServerHttpRequest {
}
/**
- * Creates an HTTP OPTIONS builder with the given url.
+ * HTTP OPTIONS variant. See {@link #get(String, Object...)} for general info.
* @param urlTemplate a URL template; the resulting URL will be encoded
* @param uriVars zero or more URI variables
* @return the created builder
@@ -225,6 +230,25 @@ public class MockServerHttpRequest extends AbstractServerHttpRequest {
*/
B contextPath(String contextPath);
+ /**
+ * Append the given query parameter to the existing query parameters.
+ * If no values are given, the resulting URI will contain the query
+ * parameter name only (i.e. {@code ?foo} instead of {@code ?foo=bar}).
+ * The provided query name and values will be encoded.
+ * @param name the query parameter name
+ * @param values the query parameter values
+ * @return this UriComponentsBuilder
+ */
+ B queryParam(String name, Object... values);
+
+ /**
+ * Add the given query parameters and values. The provided query name
+ * and corresponding values will be encoded.
+ * @param params the params
+ * @return this UriComponentsBuilder
+ */
+ B queryParams(MultiValueMap params);
+
/**
* Set the remote address to return.
*/
@@ -375,6 +399,8 @@ public class MockServerHttpRequest extends AbstractServerHttpRequest {
@Nullable
private String contextPath;
+ private final UriComponentsBuilder queryParamsBuilder = UriComponentsBuilder.newInstance();
+
private final HttpHeaders headers = new HttpHeaders();
private final MultiValueMap cookies = new LinkedMultiValueMap<>();
@@ -397,6 +423,18 @@ public class MockServerHttpRequest extends AbstractServerHttpRequest {
return this;
}
+ @Override
+ public BodyBuilder queryParam(String name, Object... values) {
+ this.queryParamsBuilder.queryParam(name, values);
+ return this;
+ }
+
+ @Override
+ public BodyBuilder queryParams(MultiValueMap params) {
+ this.queryParamsBuilder.queryParams(params);
+ return this;
+ }
+
@Override
public BodyBuilder remoteAddress(InetSocketAddress remoteAddress) {
this.remoteAddress = remoteAddress;
@@ -506,7 +544,7 @@ public class MockServerHttpRequest extends AbstractServerHttpRequest {
@Override
public MockServerHttpRequest body(Publisher extends DataBuffer> body) {
applyCookiesIfNecessary();
- return new MockServerHttpRequest(this.method, this.url, this.contextPath,
+ return new MockServerHttpRequest(this.method, getUrlToUse(), this.contextPath,
this.headers, this.cookies, this.remoteAddress, this.sslInfo, body);
}
@@ -516,6 +554,17 @@ public class MockServerHttpRequest extends AbstractServerHttpRequest {
.forEach(cookie -> this.headers.add(HttpHeaders.COOKIE, cookie.toString()));
}
}
+
+ private URI getUrlToUse() {
+ MultiValueMap params =
+ this.queryParamsBuilder.buildAndExpand().encode().getQueryParams();
+
+ if (!params.isEmpty()) {
+ return UriComponentsBuilder.fromUri(this.url).queryParams(params).build(true).toUri();
+ }
+
+ return this.url;
+ }
}
}
\ No newline at end of file