diff --git a/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcRequestConverter.java b/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcRequestConverter.java index 580bc763..74cfaf9d 100644 --- a/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcRequestConverter.java +++ b/spring-restdocs-mockmvc/src/main/java/org/springframework/restdocs/mockmvc/MockMvcRequestConverter.java @@ -156,14 +156,47 @@ private Collection extractCookies(MockHttpServletRequest mockRequ private List extractParts(MockHttpServletRequest servletRequest) throws IOException, ServletException { - List parts = new ArrayList<>(); - parts.addAll(extractServletRequestParts(servletRequest)); + List extractedPart = extractServletRequestParts(servletRequest); + List parts = new ArrayList<>(extractedPart); if (servletRequest instanceof MockMultipartHttpServletRequest) { - parts.addAll(extractMultipartRequestParts((MockMultipartHttpServletRequest) servletRequest)); + List extractedMultipartPart = extractMultipartRequestParts( + (MockMultipartHttpServletRequest) servletRequest); + + for (OperationRequestPart candidate : extractedMultipartPart) { + boolean isDuplicated = false; + for (OperationRequestPart part : extractedPart) { + isDuplicated = checkIsDuplicated(candidate, part); + + if (isDuplicated) { + extractedPart.remove(part); + break; + } + } + if (!isDuplicated) { + parts.add(candidate); + } + } } return parts; } + private static boolean checkIsDuplicated(OperationRequestPart candidate, OperationRequestPart part) { + boolean isDuplicated; + boolean isDuplicatedName = candidate.getName().equals(part.getName()); + boolean isDuplicatedFileName = (candidate.getSubmittedFileName() == null && part.getSubmittedFileName() == null) + || candidate.getSubmittedFileName().equals(part.getSubmittedFileName()); + boolean isDuplicatedContent = candidate.getContentAsString().equals(part.getContentAsString()); + + HttpHeaders candidateHeaders = new HttpHeaders(); + candidateHeaders.putAll(candidate.getHeaders()); + candidateHeaders.setContentDispositionFormData(candidate.getName(), candidate.getSubmittedFileName()); + HttpHeaders partHeaders = part.getHeaders(); + + boolean isDuplicatedHeaders = candidateHeaders.equals(partHeaders); + isDuplicated = isDuplicatedName && isDuplicatedFileName && isDuplicatedContent && isDuplicatedHeaders; + return isDuplicated; + } + private List extractServletRequestParts(MockHttpServletRequest servletRequest) throws IOException, ServletException { List parts = new ArrayList<>(); diff --git a/spring-restdocs-mockmvc/src/test/java/org/springframework/restdocs/mockmvc/MockMvcRequestConverterTests.java b/spring-restdocs-mockmvc/src/test/java/org/springframework/restdocs/mockmvc/MockMvcRequestConverterTests.java index 397b7ed7..7c23c6eb 100644 --- a/spring-restdocs-mockmvc/src/test/java/org/springframework/restdocs/mockmvc/MockMvcRequestConverterTests.java +++ b/spring-restdocs-mockmvc/src/test/java/org/springframework/restdocs/mockmvc/MockMvcRequestConverterTests.java @@ -29,6 +29,7 @@ import org.springframework.http.MediaType; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockMultipartFile; +import org.springframework.mock.web.MockPart; import org.springframework.mock.web.MockServletContext; import org.springframework.restdocs.operation.OperationRequest; import org.springframework.restdocs.operation.OperationRequestPart; @@ -187,6 +188,36 @@ public void mockMultipartFileUploadWithContentType() { assertThat(part.getContent()).isEqualTo(new byte[] { 1, 2, 3, 4 }); } + @Test + public void mockMultipartFileUploadByPart() { + OperationRequest request = createOperationRequest( + MockMvcRequestBuilders.multipart("/foo").part(new MockPart("file", "", new byte[] { 1, 2, 3, 4 }))); + assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo")); + assertThat(request.getMethod()).isEqualTo(HttpMethod.POST); + assertThat(request.getParts().size()).isEqualTo(1); + OperationRequestPart part = request.getParts().iterator().next(); + assertThat(part.getName()).isEqualTo("file"); + assertThat(part.getSubmittedFileName()).isNull(); + assertThat(part.getHeaders().size()).isEqualTo(2); + assertThat(part.getHeaders().getContentLength()).isEqualTo(4L); + assertThat(part.getHeaders().getContentDisposition().toString()).isEqualTo("form-data; name=\"file\""); + assertThat(part.getContent()).isEqualTo(new byte[] { 1, 2, 3, 4 }); + } + + @Test + public void mockMultiPartFileUploadByPartAndFile() { + OperationRequest request = createOperationRequest(MockMvcRequestBuilders.multipart("/foo") + .part(new MockPart("file", "original", new byte[] { 1, 2, 3, 4 })) + .part(new MockPart("file", "original", new byte[] { 1, 2, 3, 4 })) + .file(new MockMultipartFile("file", "original", null, new byte[] { 1, 2, 3, 4 })) + .part(new MockPart("file_part_only", "original_part_only", new byte[] { 5, 6, 7 })) + .file(new MockMultipartFile("file_file_only", "original_file_only", null, new byte[] { 8, 9, 10 }))); + + assertThat(request.getUri()).isEqualTo(URI.create("http://localhost/foo")); + assertThat(request.getMethod()).isEqualTo(HttpMethod.POST); + assertThat(request.getParts().size()).isEqualTo(5); + } + @Test public void requestWithPart() throws IOException { MockHttpServletRequest mockRequest = MockMvcRequestBuilders.get("/foo").buildRequest(new MockServletContext());