测试多部分表单数据发布请求

时间:2020-07-10 12:47:26

标签: java angular spring-mvc junit4 mockmvc

我正在尝试在spring mvc中编写一个控制器的单元测试,该控制器接受带有文件的mulitpart表单数据以及其他表单数据。我可以在测试时将请求发送到控制器,但无法访问文件或发送的数据。在控制器中收到的文件项似乎为空,在下面的代码中标记为“ fileItemsEmpty”。我能够点击api并从UI发送实际数据。非常感谢您的帮助。

ControllerCode:

@RequestMapping(value = "/upload-file", method = RequestMethod.POST, produces = CommonConstants.PRODUCES_JSON)
    @ResponseBody
    public String uploadFile(HttpServletRequest request, @NonNull Principal principal) throws Exception {
      try {
      String attribute1 = "";
      String attribute2 = "";
        List<FileItem> items = new ServletFileUpload(new DiskFileItemFactory()).parseRequest(request);
   fileItemsEmpty -> for (FileItem item : items) {
                    if(item.isFormField()) {
                      switch (item.getFieldName()) {
                            case "Attribute1":
                                attribute1 = item.getString("UTF-8");
                                break;
                            case "Attribute2":
                                attribute2 = item.getString("UTF-8");
                                break;
                            default:
                                log.info("Unknown Attribute received {}",
                                        item.getFieldName());
                        }
                    } else {
                        BufferedReader br = new BufferedReader(new InputStreamReader(item.getInputStream(), StandardCharsets.UTF_8.name()));
    
                        String line = br.readLine();
                        while (line != null) {
                          //some computation from the file
                        }
                        br.close();
                    }
                }
                } catch (FileUploadException e) {
                e.printStacktrace();
                }
                //Perform computation based on attribute1 and attribute2 and return string data.
            }

单元测试:

    @Test
    public void testfileUpload() throws Exception {

        MockMultipartFile file = new MockMultipartFile("file", "file.txt", "", "file contents".getBytes());
        MockMultipartFile attribute1 = new MockMultipartFile("Attribute1", "", "", "attribute1 value".getBytes());
        MockMultipartFile attribute2 = new MockMultipartFile("Attribute2", "", "", "attribute2 value".getBytes());

        HashMap<String, String> contentTypeParams = new HashMap<String, String>();
        contentTypeParams.put("boundary", "----WebKitFormBoundary");
        MediaType mediaType = new MediaType("multipart", "form-data", contentTypeParams);


        MvcResult mvcResult =  mockMvc.perform(MockMvcRequestBuilders.fileUpload("/upload-file")
                .file(file)
                .file(attribute1)
                .file(attribute2)
                .contentType(mediaType)
                .principal(principal))
                .andExpect(status().isOk()).andReturn();
    }

角度代码:

uploadFile(event) {
    event.target.disabled = true;
    var formData = new FormData();
    formData.append('Attribute1', 'value1');
    formData.append('Attribute2', value2);
    formData.append('file', $('#fileInput')[0].files[0]);
    this.http.post<any>("/upload-file", formData);
}

1 个答案:

答案 0 :(得分:0)

您正在使用以下方法覆盖您的实际文件:

 .file(file)
 .file(attribute1)
 .file(attribute2)

attribute1attribute2都是附加的表单数据,而不是文件。您不应该使用MockMultipartFile来创建它们,而只能使用实际文件(语音图像,pdf,docx)来创建它们。

您可以使用MockMvc.param()的另一种方法来设置其他表单数据。

因此,请尝试以下操作:

MvcResult mvcResult =  mockMvc
   .perform(MockMvcRequestBuilders.fileUpload("/upload-file")
   .file(file)
   .param("Attribute1", "attribute1")
   .param("Attribute2", "attribute2")
   .contentType(mediaType)
   .principal(principal))
   .andExpect(status().isOk()).andReturn();

PS:.fileUpload()已过时(至少在Spring Test 5.2.6中已弃用),您应该改为使用.multipart()