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

升级Spring Data JPA与Mockito后,when().thenThrow()对JPARepository.findAll失效

问题分析与修复方案

核心问题

你的测试逻辑存在一个关键漏洞:测试中mock的specification对象,和getCars方法实际生成的Specification实例完全不是同一个,导致你设置的「抛出异常」mock规则从未触发。旧版本能运行属于巧合,升级后Mockito/Spring的匹配逻辑更严谨,问题就暴露出来了。

具体修复步骤

1. 修正Mock规则,匹配任意Specification实例

放弃使用@Mock的specification对象,改用Mockito匹配器匹配所有Specification类型参数,同时建议用@MockBean替代@SpyBean(SpyBean会保留真实Repository的部分行为,可能干扰mock逻辑):

@SpringBootTest
class CarServiceTest {

    @Autowired
    CarService carService;

    @MockBean // 完全mock掉Repository,避免真实逻辑干扰
    CarRepository repository;

    @Test
    void shouldThrowError() {
        CarParams params = CarParams.builder().manufacturer("Toyota").build();
        // 直接创建真实Pageable实例,比@Mock更可靠
        Pageable pageable = PageRequest.of(0, 10);

        // 匹配任意Specification和Pageable,触发异常
        when(repository.findAll(any(Specification.class), any(Pageable.class)))
                .thenThrow(new RuntimeException("exception"));

        assertThrows(RuntimeException.class, () -> carService.getCars(params, pageable));
    }
}

2. 修正getCars方法的语法错误

你提供的getCars代码存在括号配对错误,先修正确保逻辑正常:

public PagedCarResponse getCars(CarParams params, Pageable pageable) {
    Page<Car> cars = Try.of(() -> repository.findAll(
            where(CarSpecifications.manufacturerEquals(params.getManufacturer())), 
            pageable
        ))
        .getOrElseThrow(exception -> new RuntimeException(exception));
    // 补充后续返回逻辑
}

3. 清理冗余代码

测试类中@Mock CarParams params被局部变量覆盖,属于冗余代码,建议删除。

为什么旧版本能工作?

旧版本的Mockito或Spring Data JPA对Specification的equals判断逻辑更宽松,或者SpyBean的行为存在特殊处理,导致不匹配的mock规则意外生效,但这种测试逻辑本身是不严谨的。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 09:35:11