You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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:

错误原因

  1. Mockito匹配器误用:anyInt()是Mockito专属的参数匹配器,仅能在when()或verify()等Mockito方法上下文中使用,不能直接拼接到URL字符串作为请求参数。这种错误用法触发了InvalidUseOfMatchersException。
  2. 接口执行异常:参数错误导致接口内部抛出异常,返回的是错误信息的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 00:45:56