Spring Boot中RestController单元测试when方法报错求助
Spring Boot RestController单元测试错误修复方案
问题场景
编写Spring Boot的RestController单元测试时,listBook接口的测试代码执行报错,核心是请求参数构建环节误用Mockito匹配器,导致接口执行异常,断言失败。
RestController方法
@GetMapping("/search") public ResponseEntity<List<BookResponse>> listBook(@RequestParam(name = "size") int size, @RequestParam(name = "page") int page) { final Long userID = userService.findInContextUser().getId(); return ResponseEntity.ok(bookListService.listBooks(size, page, userID)); }
原错误测试代码
@Test void itShouldGetBooks_WhenSearch() throws Exception { // given - precondition or setup BookResponse response1 = BookResponse.builder() .title("Book 1") .authorName("authorName") .build(); BookResponse response2 = BookResponse.builder() .title("Book 1") .authorName("authorName2") .build(); List<BookResponse> response = List.of(response1, response2); UserDto userDto = UserDto.builder() .id(1L) .username("username") .build(); // when - action or the behaviour that we are going test when(userService.findInContextUser()).thenReturn(userDto); when(bookListService.listBooks(anyInt(), anyInt(), eq(userDto.getId()))).thenReturn(response); // then - verify the output mockMvc.perform(get("/api/v1/book/search?size=" + anyInt() + "&page=" + anyInt()) // 错误行 .contentType(MediaType.APPLICATION_JSON)) .andDo(print()) .andExpect(jsonPath("$", hasSize(2))) // 断言失败行 .andExpect(status().isOk()); }
报错信息
java.lang.AssertionError: JSON path "$" Expected: a collection with size <2> but: was LinkedHashMap <{error=Request processing failed; nested exception is org.mockito.exceptions.misusing.InvalidUseOfMatchersException: Invalid use of argument matchers! 0 matchers expected, 2 recorded:
错误原因
- Mockito匹配器误用:
anyInt()是Mockito专属的参数匹配器,仅能在when()或verify()等Mockito方法上下文中使用,不能直接拼接到URL字符串作为请求参数。这种错误用法触发了InvalidUseOfMatchersException。 - 接口执行异常:参数错误导致接口内部抛出异常,返回的是错误信息的LinkedHashMap,而非预期的BookResponse列表,因此
jsonPath("$", hasSize(2))断言失败。
修复方案
核心修复点
将URL中错误使用的anyInt()替换为具体整数,并改用.param()方法构建请求参数(更规范)。Mockito的when()配置本身是正确的,无需修改。
修复后的完整测试代码
@Test void itShouldGetBooks_WhenSearch() throws Exception { // given - precondition or setup BookResponse response1 = BookResponse.builder() .title("Book 1") .authorName("authorName") .build(); BookResponse response2 = BookResponse.builder() .title("Book 1") .authorName("authorName2") .build(); List<BookResponse> response = List.of(response1, response2); UserDto userDto = UserDto.builder() .id(1L) .username("username") .build(); // when - action or the behaviour that we are going test when(userService.findInContextUser()).thenReturn(userDto); when(bookListService.listBooks(anyInt(), anyInt(), eq(userDto.getId()))).thenReturn(response); // then - verify the output mockMvc.perform(get("/api/v1/book/search") .param("size", "10") // 使用具体数值作为参数 .param("page", "0") .contentType(MediaType.APPLICATION_JSON)) .andDo(print()) .andExpect(jsonPath("$", hasSize(2))) .andExpect(status().isOk()); }
额外优化建议
- 用
.param()方法添加请求参数,比直接拼接URL更清晰,避免字符串拼接错误。 - 若需测试多组
size和page值,可使用@ParameterizedTest实现参数化测试,覆盖更多场景。
内容的提问来源于stack exchange,提问作者Sercan Noyan Germiyanoğlu
相关产品推荐
相关产品推荐

