Spring 测试:为数据文件发送多部分

Spring Tests: sending multipart for data file

在我们的 Spring 引导应用程序中,我们从这样的请求中获取一个多部分形式的数据文件:

  ServletFileUpload upload = new ServletFileUpload();
        try {
            FileItemIterator iterStream = upload.getItemIterator(request);
            while (iterStream.hasNext()) {
                FileItemStream item = iterStream.next();
                if (item.getFieldName().equals("file")) {
                    return upload(
                            item.getName(),
                            item.getContentType(),
                            item.openStream()
                    );
                }
            }

现在我正在编写一个用于下载文件的集成测试。我使用 mockMvc 发送请求。我尝试了很多不同的选择:

   File dataFile = resourceLoader.getResource("classpath:data/fakeload/test.pdf").getFile();
                MockMultipartFile file = new MockMultipartFile("test", "test.pdf",MediaType.APPLICATION_PDF_VALUE, FileUtils.readFileToByteArray(dataFile));
                

                mockMvc.perform(multipart("/api/project-others/documents")/*.file("test.pdf",FileUtils.readFileToByteArray(dataFile))*/.file(file)
                        .with(getAuthentication("AUTH"))
                                        .contentType(MediaType.MULTIPART_FORM_DATA_VALUE+";boundary=----WebKitFormBoundarylRihI4R4f6S5eHA2")
                                .requestAttr("file",FileUtils.readFileToByteArray(dataFile))
                                //.content(createFileContent(FileUtils.readFileToByteArray(dataFile),"WebKitFormBoundarylRihI4R4f6S5eHA2",MediaType.APPLICATION_PDF_VALUE,"test.pdf"))
                                .content(file.getBytes())
                                        .param("projectId","1")
                                .param("docId","1")

                        )
                        .andExpect(status().isOk())
                        .andDo(print());

            }
            private byte[] createFileContent(byte[] data, String boundary, String contentType, String fileName){
                String start = "--" + boundary + "\r\n Content-Disposition: form-data; name=\"file\"; filename=\""+fileName+"\"\r\n"
                        + "Content-type: "+contentType+"\r\n\r\n";;

                String end = "\r\n--" + boundary + "--"; // correction suggested @butfly
                return ArrayUtils.addAll(start.getBytes(),ArrayUtils.addAll(data,end.getBytes()));
            }

但是iterStream.hasNext()总是false(iterStream是空的)。我错过了什么?怎么了?

我想通了,我的错误是 boundary 的值 boundary=----WebKitFormBoundarylRihI4R4f6S5eHA2 - 错误 边界像 = q1w2e3r4t5y6u7i8o9 -right

正确的测试代码:

            @Test
        public void when_creating_document_expect_created_doc() throws Exception {
            FileInputStream dataFile = new FileInputStream(resourceLoader.getResource("classpath:data/fakeload/test.pdf").getFile());
            byte[] dataBytes = dataFile.readAllBytes();

            postCreateDocument(USER_NAME, 1L, 1L, dataBytes)
                    .andExpect(status().isOk())
                    .andExpect(jsonPath("$.id").value(3))
                    .andDo(print());
            ;

        }

        private ResultActions postCreateDocument(String username, Long projectOtherId, Long propertyId,
                                                 byte[] bytes) throws Exception {

            String boundary = "q1w2e3r4t5y6u7i8o9";

            var request = MockMvcRequestBuilders
                    .multipart("/api/project-others/documents")
                    .content(createFileContent(bytes, boundary, MediaType.APPLICATION_PDF_VALUE, "test.pdf"))
                    .param("projectOtherId", String.valueOf(projectOtherId))
                    .param("docTypeId", String.valueOf(propertyId))
                    .contentType("multipart/form-data; boundary=" + boundary)
                    .accept(MediaType.APPLICATION_JSON);

            if (username != null) {
                request.with(getAuthentication(username));
            }

            return mockMvc.perform(request);
        }

        public byte[] createFileContent(byte[] data, String boundary, String contentType, String fileName) {
            String start = "--" + boundary + "\r\n Content-Disposition: form-data; name=\"file\"; filename=\"" + fileName + "\"\r\n"
                    + "Content-type: " + contentType + "\r\n\r\n";
            String end = "\r\n--" + boundary + "--";
            return ArrayUtils.addAll(start.getBytes(), ArrayUtils.addAll(data, end.getBytes()));
        }

    }