From e311d9848a2f09789c7ab858f6c8a06f934ae238 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Nicoll?= Date: Mon, 9 Sep 2024 14:46:05 +0200 Subject: [PATCH] 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 --- .../mock/web/MockHttpServletRequest.java | 21 +++++++++ ...AbstractMockHttpServletRequestBuilder.java | 17 +++++-- .../servlet/assertj/MockMvcTesterTests.java | 41 +++++++++------- ...actMockHttpServletRequestBuilderTests.java | 47 +++++++++++++++++-- 4 files changed, 103 insertions(+), 23 deletions(-) diff --git a/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java b/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java index 37256c15ef..eb8911a93b 100644 --- a/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java +++ b/spring-test/src/main/java/org/springframework/mock/web/MockHttpServletRequest.java @@ -256,6 +256,9 @@ public class MockHttpServletRequest implements HttpServletRequest { @Nullable private String requestedSessionId; + @Nullable + private String uriTemplate; + @Nullable private String requestURI; @@ -1284,6 +1287,24 @@ public class MockHttpServletRequest implements HttpServletRequest { return this.requestedSessionId; } + /** + * Set the original URI template used to prepare the request, if any. + * @param uriTemplate the URI template used to set up the request, if any + * @since 6.2 + */ + public void setUriTemplate(@Nullable String uriTemplate) { + this.uriTemplate = uriTemplate; + } + + /** + * Return the original URI template used to prepare the request, if any. + * @since 6.2 + */ + @Nullable + public String getUriTemplate() { + return this.uriTemplate; + } + public void setRequestURI(@Nullable String requestURI) { this.requestURI = requestURI; } diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/request/AbstractMockHttpServletRequestBuilder.java b/spring-test/src/main/java/org/springframework/test/web/servlet/request/AbstractMockHttpServletRequestBuilder.java index cad0193887..84e7cb47ef 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/request/AbstractMockHttpServletRequestBuilder.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/request/AbstractMockHttpServletRequestBuilder.java @@ -82,6 +82,9 @@ public abstract class AbstractMockHttpServletRequestBuilder tester.get().uri("/hello"))) - .satisfies(hasSettings(HttpMethod.GET, "/hello")); + assertThat(createMockHttpServletRequest(tester -> tester.get().uri("/hello/{id}", "world"))) + .satisfies(hasSettings(HttpMethod.GET, "/hello/{id}", "/hello/world")); } @Test void headConfiguresBuilder() { - assertThat(createMockHttpServletRequest(tester -> tester.head().uri("/download"))) - .satisfies(hasSettings(HttpMethod.HEAD, "/download")); + assertThat(createMockHttpServletRequest(tester -> tester.head().uri("/download/{file}", "test.json"))) + .satisfies(hasSettings(HttpMethod.HEAD, "/download/{file}", "/download/test.json")); } @Test void postConfiguresBuilder() { - assertThat(createMockHttpServletRequest(tester -> tester.post().uri("/save"))) - .satisfies(hasSettings(HttpMethod.POST, "/save")); + assertThat(createMockHttpServletRequest(tester -> tester.post().uri("/save/{id}", 123))) + .satisfies(hasSettings(HttpMethod.POST, "/save/{id}", "/save/123")); } @Test void putConfiguresBuilder() { - assertThat(createMockHttpServletRequest(tester -> tester.put().uri("/save"))) - .satisfies(hasSettings(HttpMethod.PUT, "/save")); + assertThat(createMockHttpServletRequest(tester -> tester.put().uri("/save/{id}", 123))) + .satisfies(hasSettings(HttpMethod.PUT, "/save/{id}", "/save/123")); } @Test void patchConfiguresBuilder() { - assertThat(createMockHttpServletRequest(tester -> tester.patch().uri("/update"))) - .satisfies(hasSettings(HttpMethod.PATCH, "/update")); + assertThat(createMockHttpServletRequest(tester -> tester.patch().uri("/update/{id}", 123))) + .satisfies(hasSettings(HttpMethod.PATCH, "/update/{id}", "/update/123")); } @Test void deleteConfiguresBuilder() { - assertThat(createMockHttpServletRequest(tester -> tester.delete().uri("/users/42"))) - .satisfies(hasSettings(HttpMethod.DELETE, "/users/42")); + assertThat(createMockHttpServletRequest(tester -> tester.delete().uri("/users/{id}", 42))) + .satisfies(hasSettings(HttpMethod.DELETE, "/users/{id}", "/users/42")); } @Test void optionsConfiguresBuilder() { - assertThat(createMockHttpServletRequest(tester -> tester.options().uri("/users"))) - .satisfies(hasSettings(HttpMethod.OPTIONS, "/users")); + assertThat(createMockHttpServletRequest(tester -> tester.options().uri("/users/{id}", 42))) + .satisfies(hasSettings(HttpMethod.OPTIONS, "/users/{id}", "/users/42")); } @Test void methodConfiguresBuilderWithCustomMethod() { HttpMethod customMethod = HttpMethod.valueOf("CUSTOM"); assertThat(createMockHttpServletRequest(tester -> tester.method(customMethod).uri("/hello"))) - .satisfies(hasSettings(customMethod, "/hello")); + .satisfies(hasSettings(customMethod, "/hello", "/hello")); + } + + @Test + void methodConfiguresBuilderWithFullURI() { + assertThat(createMockHttpServletRequest(tester -> tester.get().uri(URI.create("/hello/world")))) + .satisfies(hasSettings(HttpMethod.GET, null, "/hello/world")); } private MockHttpServletRequest createMockHttpServletRequest(Function builder) { @@ -200,9 +208,10 @@ class MockMvcTesterTests { return builder.apply(mockMvcTester).buildRequest(this.servletContext); } - private Consumer hasSettings(HttpMethod method, String uri) { + private Consumer hasSettings(HttpMethod method, @Nullable String uriTemplate, String uri) { return request -> { assertThat(request.getMethod()).isEqualTo(method.name()); + assertThat(request.getUriTemplate()).isEqualTo(uriTemplate); assertThat(request.getRequestURI()).isEqualTo(uri); }; } diff --git a/spring-test/src/test/java/org/springframework/test/web/servlet/request/AbstractMockHttpServletRequestBuilderTests.java b/spring-test/src/test/java/org/springframework/test/web/servlet/request/AbstractMockHttpServletRequestBuilderTests.java index 7c40b5dff9..ef7c577f6f 100644 --- a/spring-test/src/test/java/org/springframework/test/web/servlet/request/AbstractMockHttpServletRequestBuilderTests.java +++ b/spring-test/src/test/java/org/springframework/test/web/servlet/request/AbstractMockHttpServletRequestBuilderTests.java @@ -16,6 +16,8 @@ package org.springframework.test.web.servlet.request; +import java.net.URI; + import jakarta.servlet.ServletContext; import org.junit.jupiter.api.Test; @@ -34,16 +36,53 @@ class AbstractMockHttpServletRequestBuilderTests { private final ServletContext servletContext = new MockServletContext(); + @Test + void uriTemplateSetsRequestsUrlAndTemplateConsistently() { + MockHttpServletRequest request = buildRequest(new TestRequestBuilder(HttpMethod.GET).uri("/hotels/{id}", 42)); + assertThat(request.getRequestURL().toString()).isEqualTo("http://localhost/hotels/42"); + assertThat(request.getUriTemplate()).isEqualTo("/hotels/{id}"); + } @Test - void mergeUriWhenUriIsNotSet() { - TestRequestBuilder parentBuilder = new TestRequestBuilder(HttpMethod.GET).uri("/test"); + void uriSetsRequestsUrlAndTemplateConsistently() { + MockHttpServletRequest request = buildRequest(new TestRequestBuilder(HttpMethod.GET).uri("/hotels/{id}", 42) + .uri(URI.create("/hotels/25"))); + assertThat(request.getRequestURL().toString()).isEqualTo("http://localhost/hotels/25"); + assertThat(request.getUriTemplate()).isNull(); + } + + @Test + void mergeUriTemplateWhenUriTemplateIsNotSet() { + TestRequestBuilder parentBuilder = new TestRequestBuilder(HttpMethod.GET).uri("/hotels/{id}", 42); TestRequestBuilder builder = new TestRequestBuilder(HttpMethod.POST); builder.merge(parentBuilder); MockHttpServletRequest request = buildRequest(builder); - assertThat(request.getRequestURI()).isEqualTo("/test"); - assertThat(request.getMethod()).isEqualTo(HttpMethod.POST.name()); + assertThat(request.getUriTemplate()).isEqualTo("/hotels/{id}"); + assertThat(request.getRequestURL().toString()).isEqualTo("http://localhost/hotels/42"); + } + + + @Test + void mergeUriTemplateWhenUriIsSetDoesNotMergeUriTemplate() { + TestRequestBuilder parentBuilder = new TestRequestBuilder(HttpMethod.GET).uri("/hotels/{id}", 42); + TestRequestBuilder builder = new TestRequestBuilder(HttpMethod.POST).uri(URI.create("/hotels/35")); + builder.merge(parentBuilder); + + MockHttpServletRequest request = buildRequest(builder); + assertThat(request.getUriTemplate()).isNull(); + assertThat(request.getRequestURL().toString()).isEqualTo("http://localhost/hotels/35"); + } + + @Test + void mergeUriTemplateWhenUriTemplateIsSetDoesNotMergeUriTemplate() { + TestRequestBuilder parentBuilder = new TestRequestBuilder(HttpMethod.GET).uri("/hotels/{id}", 42); + TestRequestBuilder builder = new TestRequestBuilder(HttpMethod.POST).uri("/users/{id}", 25); + builder.merge(parentBuilder); + + MockHttpServletRequest request = buildRequest(builder); + assertThat(request.getUriTemplate()).isEqualTo("/users/{id}"); + assertThat(request.getRequestURL().toString()).isEqualTo("http://localhost/users/25"); } @Test