Spring 使用 Map 参数在控制器上启动补丁请求。用 mockmvc 测试

Spring boot patch request on controller with Map parameter. Test with mockmvc

我正在尝试从我的 CompanyController 中测试一个 'patch request',它有一个 Map 和 Id 作为参数。我希望得到一个 HTTP 状态 200,但我得到一个 HTTP 状态 400。 有人可以向我解释我做错了什么吗?谢谢

CompanyController(部分代码省略):

@RestController
public class CompanyController {

    @Autowired
    private CompanyService companyService;

    @PatchMapping("companies/{id}")
    public ResponseEntity<CompanyDTO> patchUpdateCompany(@PathVariable Integer id,
                                                         @RequestBody Map<String, Object> updates) throws JsonMappingException {

        Optional<CompanyDTO> optionalCompanyDTO = this.companyService.patchUpdateCompany(updates, id);

        return ResponseEntity.ok(optionalCompanyDTO.get());
    }

}

CompanyControllerTest(部分代码省略)

@WebMvcTest(CompanyController.class)
public class CompanyControllerTest {

    @MockBean
    private CompanyService companyService;

    @Autowired
    private MockMvc mockMvc;

    private static List<CompanyDTO> companyDTOList;

    @BeforeAll
    public static void beforeAll(){
        companyDTOList = new ArrayList<>();
        CompanyDTO companyDTO1 = CompanyDTO.builder().id(1).name("xavi").build();
        CompanyDTO companyDTO2 = CompanyDTO.builder().id(2).name("marteta").build();
        companyDTOList.add(companyDTO1);
        companyDTOList.add(companyDTO2);
    }

    @Test
    void givenMapAndIdWhenPatchUpdateCompanyThenReturnHttpStatusOk() throws Exception {
        Mockito.when(this.companyService.getCompanyById(1)).thenReturn(Optional.of(companyDTOList.get(0)));

        MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
        parameters.add("name", "xavi2");

        this.mockMvc.perform(patch("/companies/1")
            .contentType(MediaType.APPLICATION_JSON)
            .params(requestParams))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.name", Matchers.is("xavi2")));

    }
}

你的问题就在这里

this.mockMvc.perform(patch("/companies/1")
            .contentType(MediaType.APPLICATION_JSON)
            .params(requestParams))  <---------------------
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.name", Matchers.is("xavi2")));

    }

您将数据作为请求参数传递。但是在你的 API 中你有 @RequestBody 意味着它希望在 http 请求正文中获取数据而不是作为请求参数。

这就是为什么您会遇到 400 错误,意思是 Bad Request,这是由 Spring 匹配 URL 路径和 http 方法类型引起的,但还有一些额外的东西在您的请求中未提供 API 方法的签名中。

所以你应该使用.content(requestParams)方法在你要发送的请求正文中设置你想要的内容

Related documentation

否则,您的 API 应该使用 @RequestParam 而不是 @RequestBody 来接收先前从测试发送的请求参数输入。