From e91abd442ae004afc9bafa0026fbc3c6fcee3bfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Nicoll?= Date: Thu, 2 Oct 2025 09:22:33 +0200 Subject: [PATCH] Simplify MockHttpServletRequestBuilders hierarchy Closes gh-33231 --- .../MockHttpServletRequestBuilder.java | 186 ------------------ ...ockMultipartHttpServletRequestBuilder.java | 123 +----------- .../request/MockMvcRequestBuilders.java | 16 +- 3 files changed, 6 insertions(+), 319 deletions(-) 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 a41857078d..b1e2ce5f80 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 @@ -16,22 +16,9 @@ package org.springframework.test.web.servlet.request; -import java.net.URI; -import java.nio.charset.Charset; -import java.security.Principal; -import java.util.Locale; -import java.util.Map; - -import jakarta.servlet.http.Cookie; -import org.jspecify.annotations.Nullable; - -import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; -import org.springframework.http.MediaType; import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.mock.web.MockHttpSession; import org.springframework.test.web.servlet.MockMvc; -import org.springframework.util.MultiValueMap; /** * Default builder for {@link MockHttpServletRequest} required as input to @@ -66,177 +53,4 @@ public class MockHttpServletRequestBuilder super(httpMethod); } - - // Override to keep binary compatibility. - - @Override - public MockHttpServletRequestBuilder uri(URI uri) { - return super.uri(uri); - } - - @Override - public MockHttpServletRequestBuilder uri(String uriTemplate, @Nullable Object... uriVariables) { - return super.uri(uriTemplate, uriVariables); - } - - @Override - public MockHttpServletRequestBuilder contextPath(String contextPath) { - return super.contextPath(contextPath); - } - - @Override - public MockHttpServletRequestBuilder servletPath(String servletPath) { - return super.servletPath(servletPath); - } - - @Override - public MockHttpServletRequestBuilder pathInfo(@Nullable String pathInfo) { - return super.pathInfo(pathInfo); - } - - @Override - public MockHttpServletRequestBuilder secure(boolean secure) { - return super.secure(secure); - } - - @Override - public MockHttpServletRequestBuilder characterEncoding(Charset encoding) { - return super.characterEncoding(encoding); - } - - @Override - public MockHttpServletRequestBuilder characterEncoding(String encoding) { - return super.characterEncoding(encoding); - } - - @Override - public MockHttpServletRequestBuilder content(byte[] content) { - return super.content(content); - } - - @Override - public MockHttpServletRequestBuilder content(String content) { - return super.content(content); - } - - @Override - public MockHttpServletRequestBuilder contentType(MediaType contentType) { - return super.contentType(contentType); - } - - @Override - public MockHttpServletRequestBuilder contentType(String contentType) { - return super.contentType(contentType); - } - - @Override - public MockHttpServletRequestBuilder accept(MediaType... mediaTypes) { - return super.accept(mediaTypes); - } - - @Override - public MockHttpServletRequestBuilder accept(String... mediaTypes) { - return super.accept(mediaTypes); - } - - @Override - public MockHttpServletRequestBuilder header(String name, Object... values) { - return super.header(name, values); - } - - @Override - public MockHttpServletRequestBuilder headers(HttpHeaders httpHeaders) { - return super.headers(httpHeaders); - } - - @Override - public MockHttpServletRequestBuilder param(String name, String... values) { - return super.param(name, values); - } - - @Override - public MockHttpServletRequestBuilder params(MultiValueMap params) { - return super.params(params); - } - - @Override - public MockHttpServletRequestBuilder queryParam(String name, String... values) { - return super.queryParam(name, values); - } - - @Override - public MockHttpServletRequestBuilder queryParams(MultiValueMap params) { - return super.queryParams(params); - } - - @Override - public MockHttpServletRequestBuilder formField(String name, String... values) { - return super.formField(name, values); - } - - @Override - public MockHttpServletRequestBuilder formFields(MultiValueMap formFields) { - return super.formFields(formFields); - } - - @Override - public MockHttpServletRequestBuilder cookie(Cookie... cookies) { - return super.cookie(cookies); - } - - @Override - public MockHttpServletRequestBuilder locale(Locale... locales) { - return super.locale(locales); - } - - @Override - public MockHttpServletRequestBuilder locale(@Nullable Locale locale) { - return super.locale(locale); - } - - @Override - public MockHttpServletRequestBuilder requestAttr(String name, Object value) { - return super.requestAttr(name, value); - } - - @Override - public MockHttpServletRequestBuilder sessionAttr(String name, Object value) { - return super.sessionAttr(name, value); - } - - @Override - public MockHttpServletRequestBuilder sessionAttrs(Map sessionAttributes) { - return super.sessionAttrs(sessionAttributes); - } - - @Override - public MockHttpServletRequestBuilder flashAttr(String name, Object value) { - return super.flashAttr(name, value); - } - - @Override - public MockHttpServletRequestBuilder flashAttrs(Map flashAttributes) { - return super.flashAttrs(flashAttributes); - } - - @Override - public MockHttpServletRequestBuilder session(MockHttpSession session) { - return super.session(session); - } - - @Override - public MockHttpServletRequestBuilder principal(Principal principal) { - return super.principal(principal); - } - - @Override - public MockHttpServletRequestBuilder remoteAddress(String remoteAddress) { - return super.remoteAddress(remoteAddress); - } - - @Override - public MockHttpServletRequestBuilder with(RequestPostProcessor postProcessor) { - return super.with(postProcessor); - } - } diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockMultipartHttpServletRequestBuilder.java b/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockMultipartHttpServletRequestBuilder.java index 73c620e61e..96401516f2 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockMultipartHttpServletRequestBuilder.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockMultipartHttpServletRequestBuilder.java @@ -16,28 +16,9 @@ package org.springframework.test.web.servlet.request; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import jakarta.servlet.ServletContext; -import jakarta.servlet.http.Part; -import org.jspecify.annotations.Nullable; - import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.mock.web.MockMultipartFile; import org.springframework.mock.web.MockMultipartHttpServletRequest; -import org.springframework.util.Assert; -import org.springframework.util.FileCopyUtils; -import org.springframework.util.LinkedMultiValueMap; -import org.springframework.util.MultiValueMap; /** * Default builder for {@link MockMultipartHttpServletRequest}. @@ -47,12 +28,8 @@ import org.springframework.util.MultiValueMap; * @author Stephane Nicoll * @since 3.2 */ -public class MockMultipartHttpServletRequestBuilder extends MockHttpServletRequestBuilder { - - private final List files = new ArrayList<>(); - - private final MultiValueMap parts = new LinkedMultiValueMap<>(); - +public class MockMultipartHttpServletRequestBuilder + extends AbstractMockMultipartHttpServletRequestBuilder { /** * Package-private constructor. Use static factory methods in @@ -76,100 +53,4 @@ public class MockMultipartHttpServletRequestBuilder extends MockHttpServletReque } - /** - * Add a new {@link MockMultipartFile} with the given content. - * @param name the name of the file - * @param content the content of the file - */ - public MockMultipartHttpServletRequestBuilder file(String name, byte[] content) { - this.files.add(new MockMultipartFile(name, content)); - return this; - } - - /** - * Add the given {@link MockMultipartFile}. - * @param file the multipart file - */ - public MockMultipartHttpServletRequestBuilder file(MockMultipartFile file) { - this.files.add(file); - return this; - } - - /** - * Add {@link Part} components to the request. - * @param parts one or more parts to add - * @since 5.0 - */ - public MockMultipartHttpServletRequestBuilder part(Part... parts) { - Assert.notEmpty(parts, "'parts' must not be empty"); - for (Part part : parts) { - this.parts.add(part.getName(), part); - } - return this; - } - - @Override - public Object merge(@Nullable Object parent) { - if (parent == null) { - return this; - } - if (parent instanceof MockHttpServletRequestBuilder) { - super.merge(parent); - if (parent instanceof MockMultipartHttpServletRequestBuilder parentBuilder) { - this.files.addAll(parentBuilder.files); - parentBuilder.parts.keySet().forEach(name -> - this.parts.putIfAbsent(name, parentBuilder.parts.get(name))); - } - } - else { - throw new IllegalArgumentException("Cannot merge with [" + parent.getClass().getName() + "]"); - } - return this; - } - - /** - * Create a new {@link MockMultipartHttpServletRequest} based on the - * supplied {@code ServletContext} and the {@code MockMultipartFiles} - * added to this builder. - */ - @Override - protected final MockHttpServletRequest createServletRequest(ServletContext servletContext) { - MockMultipartHttpServletRequest request = new MockMultipartHttpServletRequest(servletContext); - Charset defaultCharset = (request.getCharacterEncoding() != null ? - Charset.forName(request.getCharacterEncoding()) : StandardCharsets.UTF_8); - - this.files.forEach(request::addFile); - this.parts.values().stream().flatMap(Collection::stream).forEach(part -> { - request.addPart(part); - try { - String name = part.getName(); - String filename = part.getSubmittedFileName(); - InputStream is = part.getInputStream(); - if (filename != null) { - request.addFile(new MockMultipartFile(name, filename, part.getContentType(), is)); - } - else { - InputStreamReader reader = new InputStreamReader(is, getCharsetOrDefault(part, defaultCharset)); - String value = FileCopyUtils.copyToString(reader); - request.addParameter(part.getName(), value); - } - } - catch (IOException ex) { - throw new IllegalStateException("Failed to read content for part " + part.getName(), ex); - } - }); - - return request; - } - - private Charset getCharsetOrDefault(Part part, Charset defaultCharset) { - if (part.getContentType() != null) { - MediaType mediaType = MediaType.parseMediaType(part.getContentType()); - if (mediaType.getCharset() != null) { - return mediaType.getCharset(); - } - } - return defaultCharset; - } - } diff --git a/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockMvcRequestBuilders.java b/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockMvcRequestBuilders.java index e2e1dcb5ca..bfef763d18 100644 --- a/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockMvcRequestBuilders.java +++ b/spring-test/src/main/java/org/springframework/test/web/servlet/request/MockMvcRequestBuilders.java @@ -215,9 +215,7 @@ public abstract class MockMvcRequestBuilders { * @since 5.0 */ public static MockMultipartHttpServletRequestBuilder multipart(String uriTemplate, @Nullable Object... uriVariables) { - MockMultipartHttpServletRequestBuilder builder = new MockMultipartHttpServletRequestBuilder(); - builder.uri(uriTemplate, uriVariables); - return builder; + return new MockMultipartHttpServletRequestBuilder().uri(uriTemplate, uriVariables); } /** @@ -229,9 +227,7 @@ public abstract class MockMvcRequestBuilders { * @since 5.3.22 */ public static MockMultipartHttpServletRequestBuilder multipart(HttpMethod httpMethod, String uriTemplate, @Nullable Object... uriVariables) { - MockMultipartHttpServletRequestBuilder builder = new MockMultipartHttpServletRequestBuilder(httpMethod); - builder.uri(uriTemplate, uriVariables); - return builder; + return new MockMultipartHttpServletRequestBuilder(httpMethod).uri(uriTemplate, uriVariables); } /** @@ -240,9 +236,7 @@ public abstract class MockMvcRequestBuilders { * @since 5.0 */ public static MockMultipartHttpServletRequestBuilder multipart(URI uri) { - MockMultipartHttpServletRequestBuilder builder = new MockMultipartHttpServletRequestBuilder(); - builder.uri(uri); - return builder; + return new MockMultipartHttpServletRequestBuilder().uri(uri); } /** @@ -253,9 +247,7 @@ public abstract class MockMvcRequestBuilders { * @since 5.3.21 */ public static MockMultipartHttpServletRequestBuilder multipart(HttpMethod httpMethod, URI uri) { - MockMultipartHttpServletRequestBuilder builder = new MockMultipartHttpServletRequestBuilder(httpMethod); - builder.uri(uri); - return builder; + return new MockMultipartHttpServletRequestBuilder(httpMethod).uri(uri); } /**