java - 测试分段文件上传时获取 400 响应代码而不是 200 代码

标签 java spring-boot mockmvc

我正在测试一个端点来上传一组多部分文件以及一个String参数。我收到的是 400 响应,而不是 200(OK)。关于为什么我收到 400 响应 的任何想法,这表明我的请求对象有问题。但是当我检查请求时,内容类型是正确的。

uploadMyFiles.java 端点

@PostMapping(path = "/uploadMyFiles", consumes = { MediaType.MULTIPART_FORM_DATA_VALUE })
public Map<String, String> uploadMyFiles(MultipartFile[] multipartFiles, String userName) {
//..
return statusMap
}

我的测试用例

@Test
 public void testUploadMyFiles() throws Exception {
        byte[] byteContent = new byte[100];
        String userName ="testUser"
        
        MockMultipartFile filePart1 = new MockMultipartFile("files", "file1.pdf", "multipart/form-data", content);
        MultipartFile[] multipartFiles={filePart1}
        
        Object resultMap;
        when(myService.uploadMyFiles(multipartFiles,userName)).thenReturn(Map.of("file1.pdf", "Success"));

        MvcResult result = this.mockMvc.perform(MockMvcRequestBuilders.multipart("/uploadMyFiles")
                            .content(userName)
                            .content("{userName:testUser}") //tried with this too
                            .param("userName", "testUser")) //tried with this too 
                            .andExpect(status().isOk())
                            .andReturn();

        assertEquals(HttpStatus.OK, ((ResponseEntity)result.getAsyncResult()).getStatusCode());
    }

调试:

MockHttpServletRequest:
      HTTP Method = POST
      Request URI = /uploadMyFiles
       Parameters = {userName=[testUser]}
          Headers = [Content-Type:"multipart/form-data", Content-Length:"23"]
             Body = <no character encoding set>
    Session Attrs = {}

回应

MockHttpServletResponse:
           Status = 400
    Error message = null
          Headers = [Vary:"Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers"]
     Content type = null
             Body = 
    Forwarded URL = null
   Redirected URL = null
          Cookies = []

最佳答案

HTTP 400(在 spring-web 中)表示 RequestMapping 仅“部分映射”...

要测试此 Controller /请求映射:

@Controller
public class MyController {
    private static final Logger LOG = LoggerFactory.getLogger(MyController.class);

    @PostMapping(path = "/uploadMyFiles", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE})
    public @ResponseBody
    Map<String, String> uploadMyFiles(MultipartFile[] multipartFiles, String userName) {
        if (multipartFiles == null) {
            LOG.warn("multipartFiles is null!");
        } else {
            LOG.info("{} file{} uploaded.", multipartFiles.length, multipartFiles.length > 1 ? "s" : "");
            if (LOG.isDebugEnabled()) {
                for (MultipartFile mf : multipartFiles) {
                    LOG.debug("name: {}, size: {}, contentType: {}", mf.getOriginalFilename(), mf.getSize(), mf.getContentType());
                }
            }
        }
        // ...
        return Map.of("foo", "bar");
    }
}

这将是 MockMvc 测试的轮廓(命中此 Controller ):

package com.example; // package of spring-boot-app

    
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.test.web.servlet.MockMvc;

import java.nio.charset.StandardCharsets;

import static org.hamcrest.Matchers.containsString;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.multipart;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@WebMvcTest
class Q66280300ApplicationTests {
    @Autowired
    private MockMvc mockMvc;

    @Test
    public void testUploadMyFiles() throws Exception {
        byte[] byteContent1 = "text1".getBytes(StandardCharsets.US_ASCII);
        byte[] byteContent2 = "text2".getBytes(StandardCharsets.US_ASCII);
        String userName = "testUser";

        // IMPORTANT: name = "multipartFiles" (name of the request parameter)
        MockMultipartFile filePart1 = new MockMultipartFile("multipartFiles", "file1.txt", "text/plain", byteContent1);
        MockMultipartFile filePart2 = new MockMultipartFile("multipartFiles", "file2.txt", "text/plain", byteContent2);

        this.mockMvc.perform(
          multipart("/uploadMyFiles")
          .file(filePart1)
          .file(filePart2)
          .param("userName", userName)
        )
        .andDo(print())
        .andExpect(status().isOk())
        .andExpect(content().string(containsString("{\"foo\":\"bar\"}")));

    }
}

要找到您的文件(在 Controller 内、日志记录、null...),至关重要MockMultipartFile 的名称必须匹配> 请求参数的名称。 (在我们的例子中,方法参数的“默认”名称:“multipartFiles”)

代码基于Spring-boot-starter:2.4.3 .

关于java - 测试分段文件上传时获取 400 响应代码而不是 200 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66280300/

相关文章:

java - 导入 org.apache.commons.net.telnet.TelnetClient;

java - 使用实体管理器时,没有为该名称定义查询

java - IN 不工作的 JPA EntityManager createQuery()

java - 如何在 Spring Boot 应用程序中模拟外部依赖关系?

java - 与单元测试 Controller 和服务方法的区别

java - XPath:以不同方式定义的节点

java - 在 JUnit 中使用(out)存储库对 Spring Boot 服务类进行单元测试

java - 多上下文 spring-boot 应用程序 : how to define standard spring-boot properties for each child context

spring-boot - 如何使用MockMVC和standaloneSetup并且没有WebApplicationContext测试Thymeleaf?

java - Controller 单元测试无法 Autowiring 所需的 bean