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

Spring Boot控制器集成测试报Wanted but not invoked错误

问题根因

报错核心是Mock对象未被Spring上下文识别,且测试逻辑存在跨层校验问题:

  • 你使用的@Mock是Mockito原生注解,仅在Mockito独立上下文生成模拟对象,不会替换@SpringBootTest启动的完整Spring容器里的真实Bean,控制器注入的BookService仍然关联容器内真实的BookRepository,你声明的BookRepository Mock对象从未被调用,自然触发找不到交互的报错。
  • 控制器层的测试边界存在越界:控制器仅直接依赖BookService,和BookRepository没有直接交互,只要你Mock了BookService,Mock对象默认不会执行内部真实逻辑,根本不会透传调用到BookRepository,这行verify(bookRepository).findAll(...)的校验逻辑本身就不符合分层测试的设计。
修复方案

方案1:保留全链路校验逻辑(测试运行速度慢,非必要不推荐)

如果需要在当前测试中覆盖从控制器到Repository的完整调用链路:

  • 移除BookService的@Mock注解,使用容器中真实的BookService实例
  • 将BookRepository的@Mock注解替换为Spring Boot测试提供的@MockBean注解,该注解会自动将模拟对象注入Spring容器,替换同类型的真实Bean
  • 提前配置Repository层的桩方法返回模拟数据:
    Page<Book> mockPage = new PageImpl<>(List.of(new Book(), new Book()));
    when(bookRepository.findAll(any(Pageable.class))).thenReturn(mockPage);
    when(bookService.findAllCategories()).thenReturn(List.of("文学", "计算机"));
    
  • 执行请求后再调用verify(bookRepository).findAll(pageableCaptor.capture())即可正常捕获参数,配合你自定义的PageableAssert完成断言。

方案2:遵循分层测试规范(推荐)

控制器层测试只需要校验控制器自身的参数处理、视图返回、和Service层的交互逻辑即可,Repository层的调用校验应该下移到Service层的单元测试中:

  • 移除测试类中所有BookRepository相关的模拟、校验逻辑,不要在控制器测试中跨层操作Repository
  • 将BookService的@Mock注解替换为@MockBean,提前配置Service层的桩方法返回模拟数据:
    Page<Book> mockPage = new PageImpl<>(List.of(new Book(), new Book()));
    when(bookService.getAllBooks(any(Pageable.class))).thenReturn(mockPage);
    when(bookService.findAllCategories()).thenReturn(List.of("文学", "计算机"));
    
  • 调整校验逻辑,仅验证控制器的行为符合预期:
    • 校验GET请求返回的视图名称为library
    • 校验Model中存入的分页结果、分类列表、页码列表数据和预期一致
    • 捕获传给bookService.getAllBooks方法的Pageable参数,用自定义的PageableAssert校验分页参数、排序规则是否正确,示例代码:
      ArgumentCaptor<Pageable> pageableCaptor = ArgumentCaptor.forClass(Pageable.class);
      verify(bookService).getAllBooks(pageableCaptor.capture());
      Pageable capturedPageable = pageableCaptor.getValue();
      assertThat(capturedPageable)
          .hasPageNumber(0)
          .hasPageSize(10)
          .isSortedBy("createTime");
      
  • 单独编写BookService的单元测试,使用@ExtendWith(MockitoExtension.class)+@Mock注入BookRepository,在Service层测试中完成bookRepository.findAll()调用的校验逻辑,不需要启动Spring上下文,测试运行速度更快、定位问题更精准。
关键注意点
  • 不要混淆@Mock和@MockBean的适用场景:@Mock仅适用于不启动Spring容器的纯单元测试,@MockBean才适用于@SpringBootTest启动容器的集成测试,用来替换容器内的真实Bean。
  • 分层测试不要跨层校验:Web层测试只校验请求处理、视图跳转、参数传递逻辑,Service层测试校验业务逻辑和Repository交互,Repository层测试校验数据查询逻辑,避免测试逻辑冗余、耦合度高。

内容的提问来源于stack exchange,提问作者Oleksandr Ovcharenko

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 12:18:18