Skip to content

Commit e311d98

Browse files
committed
Expose the uriTemplate used to build a MockHttpServletRequest
This commit exposes the unexpanded URI template used to build a MockHttpServletRequest. This allows MockMvc users to retrieve that information, in consistency with ExchangeResult in WebTestClient. Closes gh-33509
1 parent d2b25c0 commit e311d98

File tree

4 files changed

+103
-23
lines changed

4 files changed

+103
-23
lines changed

spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java

+21
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,9 @@ public class MockHttpServletRequest implements HttpServletRequest {
256256
@Nullable
257257
private String requestedSessionId;
258258

259+
@Nullable
260+
private String uriTemplate;
261+
259262
@Nullable
260263
private String requestURI;
261264

@@ -1284,6 +1287,24 @@ public String getRequestedSessionId() {
12841287
return this.requestedSessionId;
12851288
}
12861289

1290+
/**
1291+
* Set the original URI template used to prepare the request, if any.
1292+
* @param uriTemplate the URI template used to set up the request, if any
1293+
* @since 6.2
1294+
*/
1295+
public void setUriTemplate(@Nullable String uriTemplate) {
1296+
this.uriTemplate = uriTemplate;
1297+
}
1298+
1299+
/**
1300+
* Return the original URI template used to prepare the request, if any.
1301+
* @since 6.2
1302+
*/
1303+
@Nullable
1304+
public String getUriTemplate() {
1305+
return this.uriTemplate;
1306+
}
1307+
12871308
public void setRequestURI(@Nullable String requestURI) {
12881309
this.requestURI = requestURI;
12891310
}

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

+14-3
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@ public abstract class AbstractMockHttpServletRequestBuilder<B extends AbstractMo
8282

8383
private final HttpMethod method;
8484

85+
@Nullable
86+
private String uriTemplate;
87+
8588
@Nullable
8689
private URI uri;
8790

@@ -152,15 +155,20 @@ protected B self() {
152155
* Specify the URI using an absolute, fully constructed {@link java.net.URI}.
153156
*/
154157
public B uri(URI uri) {
155-
this.uri = uri;
156-
return self();
158+
return updateUri(uri, null);
157159
}
158160

159161
/**
160162
* Specify the URI for the request using a URI template and URI variables.
161163
*/
162164
public B uri(String uriTemplate, Object... uriVariables) {
163-
return uri(initUri(uriTemplate, uriVariables));
165+
return updateUri(initUri(uriTemplate, uriVariables), uriTemplate);
166+
}
167+
168+
private B updateUri(URI uri, @Nullable String uriTemplate) {
169+
this.uri = uri;
170+
this.uriTemplate = uriTemplate;
171+
return self();
164172
}
165173

166174
private static URI initUri(String uri, Object[] vars) {
@@ -594,6 +602,7 @@ public Object merge(@Nullable Object parent) {
594602
}
595603
if (this.uri == null) {
596604
this.uri = parentBuilder.uri;
605+
this.uriTemplate = parentBuilder.uriTemplate;
597606
}
598607
if (!StringUtils.hasText(this.contextPath)) {
599608
this.contextPath = parentBuilder.contextPath;
@@ -707,6 +716,8 @@ public final MockHttpServletRequest buildRequest(ServletContext servletContext)
707716
request.setAsyncSupported(true);
708717
request.setMethod(this.method.name());
709718

719+
request.setUriTemplate(this.uriTemplate);
720+
710721
String requestUri = this.uri.getRawPath();
711722
request.setRequestURI(requestUri);
712723

spring-test/src/test/java/org/springframework/test/web/servlet/assertj/MockMvcTesterTests.java

+25-16
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package org.springframework.test.web.servlet.assertj;
1818

19+
import java.net.URI;
1920
import java.util.LinkedHashMap;
2021
import java.util.List;
2122
import java.util.concurrent.atomic.AtomicInteger;
@@ -34,6 +35,7 @@
3435
import org.springframework.http.HttpStatus;
3536
import org.springframework.http.MediaType;
3637
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
38+
import org.springframework.lang.Nullable;
3739
import org.springframework.mock.web.MockHttpServletRequest;
3840
import org.springframework.mock.web.MockServletContext;
3941
import org.springframework.test.json.AbstractJsonContentAssert;
@@ -148,61 +150,68 @@ void performWithUnresolvedExceptionSetsException() {
148150

149151
@Test
150152
void getConfiguresBuilder() {
151-
assertThat(createMockHttpServletRequest(tester -> tester.get().uri("/hello")))
152-
.satisfies(hasSettings(HttpMethod.GET, "/hello"));
153+
assertThat(createMockHttpServletRequest(tester -> tester.get().uri("/hello/{id}", "world")))
154+
.satisfies(hasSettings(HttpMethod.GET, "/hello/{id}", "/hello/world"));
153155
}
154156

155157
@Test
156158
void headConfiguresBuilder() {
157-
assertThat(createMockHttpServletRequest(tester -> tester.head().uri("/download")))
158-
.satisfies(hasSettings(HttpMethod.HEAD, "/download"));
159+
assertThat(createMockHttpServletRequest(tester -> tester.head().uri("/download/{file}", "test.json")))
160+
.satisfies(hasSettings(HttpMethod.HEAD, "/download/{file}", "/download/test.json"));
159161
}
160162

161163
@Test
162164
void postConfiguresBuilder() {
163-
assertThat(createMockHttpServletRequest(tester -> tester.post().uri("/save")))
164-
.satisfies(hasSettings(HttpMethod.POST, "/save"));
165+
assertThat(createMockHttpServletRequest(tester -> tester.post().uri("/save/{id}", 123)))
166+
.satisfies(hasSettings(HttpMethod.POST, "/save/{id}", "/save/123"));
165167
}
166168

167169
@Test
168170
void putConfiguresBuilder() {
169-
assertThat(createMockHttpServletRequest(tester -> tester.put().uri("/save")))
170-
.satisfies(hasSettings(HttpMethod.PUT, "/save"));
171+
assertThat(createMockHttpServletRequest(tester -> tester.put().uri("/save/{id}", 123)))
172+
.satisfies(hasSettings(HttpMethod.PUT, "/save/{id}", "/save/123"));
171173
}
172174

173175
@Test
174176
void patchConfiguresBuilder() {
175-
assertThat(createMockHttpServletRequest(tester -> tester.patch().uri("/update")))
176-
.satisfies(hasSettings(HttpMethod.PATCH, "/update"));
177+
assertThat(createMockHttpServletRequest(tester -> tester.patch().uri("/update/{id}", 123)))
178+
.satisfies(hasSettings(HttpMethod.PATCH, "/update/{id}", "/update/123"));
177179
}
178180

179181
@Test
180182
void deleteConfiguresBuilder() {
181-
assertThat(createMockHttpServletRequest(tester -> tester.delete().uri("/users/42")))
182-
.satisfies(hasSettings(HttpMethod.DELETE, "/users/42"));
183+
assertThat(createMockHttpServletRequest(tester -> tester.delete().uri("/users/{id}", 42)))
184+
.satisfies(hasSettings(HttpMethod.DELETE, "/users/{id}", "/users/42"));
183185
}
184186

185187
@Test
186188
void optionsConfiguresBuilder() {
187-
assertThat(createMockHttpServletRequest(tester -> tester.options().uri("/users")))
188-
.satisfies(hasSettings(HttpMethod.OPTIONS, "/users"));
189+
assertThat(createMockHttpServletRequest(tester -> tester.options().uri("/users/{id}", 42)))
190+
.satisfies(hasSettings(HttpMethod.OPTIONS, "/users/{id}", "/users/42"));
189191
}
190192

191193
@Test
192194
void methodConfiguresBuilderWithCustomMethod() {
193195
HttpMethod customMethod = HttpMethod.valueOf("CUSTOM");
194196
assertThat(createMockHttpServletRequest(tester -> tester.method(customMethod).uri("/hello")))
195-
.satisfies(hasSettings(customMethod, "/hello"));
197+
.satisfies(hasSettings(customMethod, "/hello", "/hello"));
198+
}
199+
200+
@Test
201+
void methodConfiguresBuilderWithFullURI() {
202+
assertThat(createMockHttpServletRequest(tester -> tester.get().uri(URI.create("/hello/world"))))
203+
.satisfies(hasSettings(HttpMethod.GET, null, "/hello/world"));
196204
}
197205

198206
private MockHttpServletRequest createMockHttpServletRequest(Function<MockMvcTester, MockMvcRequestBuilder> builder) {
199207
MockMvcTester mockMvcTester = MockMvcTester.of(HelloController.class);
200208
return builder.apply(mockMvcTester).buildRequest(this.servletContext);
201209
}
202210

203-
private Consumer<MockHttpServletRequest> hasSettings(HttpMethod method, String uri) {
211+
private Consumer<MockHttpServletRequest> hasSettings(HttpMethod method, @Nullable String uriTemplate, String uri) {
204212
return request -> {
205213
assertThat(request.getMethod()).isEqualTo(method.name());
214+
assertThat(request.getUriTemplate()).isEqualTo(uriTemplate);
206215
assertThat(request.getRequestURI()).isEqualTo(uri);
207216
};
208217
}

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

+43-4
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package org.springframework.test.web.servlet.request;
1818

19+
import java.net.URI;
20+
1921
import jakarta.servlet.ServletContext;
2022
import org.junit.jupiter.api.Test;
2123

@@ -34,16 +36,53 @@ class AbstractMockHttpServletRequestBuilderTests {
3436

3537
private final ServletContext servletContext = new MockServletContext();
3638

39+
@Test
40+
void uriTemplateSetsRequestsUrlAndTemplateConsistently() {
41+
MockHttpServletRequest request = buildRequest(new TestRequestBuilder(HttpMethod.GET).uri("/hotels/{id}", 42));
42+
assertThat(request.getRequestURL().toString()).isEqualTo("http://localhost/hotels/42");
43+
assertThat(request.getUriTemplate()).isEqualTo("/hotels/{id}");
44+
}
3745

3846
@Test
39-
void mergeUriWhenUriIsNotSet() {
40-
TestRequestBuilder parentBuilder = new TestRequestBuilder(HttpMethod.GET).uri("/test");
47+
void uriSetsRequestsUrlAndTemplateConsistently() {
48+
MockHttpServletRequest request = buildRequest(new TestRequestBuilder(HttpMethod.GET).uri("/hotels/{id}", 42)
49+
.uri(URI.create("/hotels/25")));
50+
assertThat(request.getRequestURL().toString()).isEqualTo("http://localhost/hotels/25");
51+
assertThat(request.getUriTemplate()).isNull();
52+
}
53+
54+
@Test
55+
void mergeUriTemplateWhenUriTemplateIsNotSet() {
56+
TestRequestBuilder parentBuilder = new TestRequestBuilder(HttpMethod.GET).uri("/hotels/{id}", 42);
4157
TestRequestBuilder builder = new TestRequestBuilder(HttpMethod.POST);
4258
builder.merge(parentBuilder);
4359

4460
MockHttpServletRequest request = buildRequest(builder);
45-
assertThat(request.getRequestURI()).isEqualTo("/test");
46-
assertThat(request.getMethod()).isEqualTo(HttpMethod.POST.name());
61+
assertThat(request.getUriTemplate()).isEqualTo("/hotels/{id}");
62+
assertThat(request.getRequestURL().toString()).isEqualTo("http://localhost/hotels/42");
63+
}
64+
65+
66+
@Test
67+
void mergeUriTemplateWhenUriIsSetDoesNotMergeUriTemplate() {
68+
TestRequestBuilder parentBuilder = new TestRequestBuilder(HttpMethod.GET).uri("/hotels/{id}", 42);
69+
TestRequestBuilder builder = new TestRequestBuilder(HttpMethod.POST).uri(URI.create("/hotels/35"));
70+
builder.merge(parentBuilder);
71+
72+
MockHttpServletRequest request = buildRequest(builder);
73+
assertThat(request.getUriTemplate()).isNull();
74+
assertThat(request.getRequestURL().toString()).isEqualTo("http://localhost/hotels/35");
75+
}
76+
77+
@Test
78+
void mergeUriTemplateWhenUriTemplateIsSetDoesNotMergeUriTemplate() {
79+
TestRequestBuilder parentBuilder = new TestRequestBuilder(HttpMethod.GET).uri("/hotels/{id}", 42);
80+
TestRequestBuilder builder = new TestRequestBuilder(HttpMethod.POST).uri("/users/{id}", 25);
81+
builder.merge(parentBuilder);
82+
83+
MockHttpServletRequest request = buildRequest(builder);
84+
assertThat(request.getUriTemplate()).isEqualTo("/users/{id}");
85+
assertThat(request.getRequestURL().toString()).isEqualTo("http://localhost/users/25");
4786
}
4887

4988
@Test

0 commit comments

Comments
 (0)