Add integration tests and docs for multipart support

This commit adds integration tests and reference documentation
 for multipart support in `RestClient` and `RestTestClient`.

Closes gh-35569
Closes gh-33263
This commit is contained in:
Brian Clozel
2026-03-26 15:10:01 +01:00
parent ab8de8ec4b
commit aac521c116
6 changed files with 213 additions and 2 deletions
@@ -24,6 +24,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
@@ -40,6 +41,8 @@ import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.HttpStatusCode;
@@ -54,6 +57,9 @@ import org.springframework.http.client.JdkClientHttpRequestFactory;
import org.springframework.http.client.JettyClientHttpRequestFactory;
import org.springframework.http.client.ReactorClientHttpRequestFactory;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.multipart.FilePart;
import org.springframework.http.converter.multipart.FormFieldPart;
import org.springframework.http.converter.multipart.Part;
import org.springframework.util.CollectionUtils;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.util.FileCopyUtils;
@@ -354,6 +360,35 @@ class RestClientIntegrationTests {
assertThat(result).isNull();
}
@ParameterizedRestClientTest
void retrieveMultipart(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);
Resource resource = new ClassPathResource("simple.multipart", getClass());
String multipartBody = Files.readString(resource.getFile().toPath());
prepareResponse(builder -> builder
.setHeader("Content-Type", "multipart/form-data; boundary=---------------------------testboundary")
.body(multipartBody));
MultiValueMap<String, Part> result = this.restClient.get()
.uri("/multipart")
.accept(MediaType.MULTIPART_FORM_DATA)
.retrieve()
.body(new ParameterizedTypeReference<>() {});
assertThat(result).hasSize(3);
assertThat(result).containsKeys("text1", "text2", "file1");
assertThat(result.get("text1").get(0)).isInstanceOfSatisfying(FormFieldPart.class, part -> assertThat(part.value()).isEqualTo("a"));
assertThat(result.get("text2").get(0)).isInstanceOfSatisfying(FormFieldPart.class, part -> assertThat(part.value()).isEqualTo("b"));
assertThat(result.get("file1").get(0)).isInstanceOfSatisfying(FilePart.class, part -> assertThat(part.filename()).isEqualTo("a.txt"));
expectRequestCount(1);
expectRequest(request -> {
assertThat(request.getTarget()).isEqualTo("/multipart");
assertThat(request.getHeaders().get(HttpHeaders.ACCEPT)).isEqualTo("multipart/form-data");
});
}
@ParameterizedRestClientTest
void retrieve404(ClientHttpRequestFactory requestFactory) throws IOException {
startServer(requestFactory);