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

使用@SpyBean模拟JpaRepository方法调用序列时的异常问题求解

解决JpaRepository SpyBean模拟异常→正常→异常调用序列的问题

你遇到的问题本质是JpaRepository是抽象接口,Mockito生成的Spy代理没有可直接调用的真实方法实现——Spring Data的Repository实现是动态生成的代理类,而doCallRealMethod()只能针对有具体实现的方法生效,所以会报错。

要实现「异常→正常→异常」的调用序列,核心思路是显式委托真实的Repository实例处理第二次调用,而不是依赖doCallRealMethod()。下面是两种可行方案:

方案一:链式调用结合doAnswer委托真实实例

直接通过链式调用定义每次调用的行为,第二次调用显式调用Spring容器中真实的Repository方法:

@Autowired
private MyRepository realMyRepository; // 注入真实的Repository实例

@SpyBean
private MyRepository mySpyBean;

@Test
void testBatchDeleteFailureSequence() {
    // 定义调用序列:第一次抛异常,第二次调用真实方法,第三次抛异常
    doThrow(new DataAccessResourceFailureException("数据库调用失败"))
        .doAnswer(invocation -> {
            // 委托给真实Repository执行deleteAll
            return realMyRepository.deleteAll(invocation.getArguments());
        })
        .doThrow(new DataAccessResourceFailureException("数据库调用失败"))
        .when(mySpyBean).deleteAll(any());

    // 执行你的服务批量处理逻辑
    yourService.handleBatchProcess();

    // 验证调用次数
    verify(mySpyBean, times(3)).deleteAll(any());
}

方案二:用计数器控制调用行为

如果需要更灵活的调用次数控制(比如不确定调用顺序但需要按次数区分),可以用AtomicInteger记录调用次数,在doAnswer中分支处理:

@Autowired
private MyRepository realMyRepository;

@SpyBean
private MyRepository mySpyBean;

@Test
void testBatchDeleteWithDynamicSequence() {
    AtomicInteger callCounter = new AtomicInteger(0);

    doAnswer(invocation -> {
        int currentCall = callCounter.incrementAndGet();
        if (currentCall == 1 || currentCall == 3) {
            throw new DataAccessResourceFailureException("数据库调用失败");
        } else {
            // 第二次调用走真实逻辑
            return realMyRepository.deleteAll(invocation.getArguments());
        }
    }).when(mySpyBean).deleteAll(any());

    // 执行服务逻辑
    yourService.handleBatchProcess();

    // 验证调用次数
    verify(mySpyBean, times(3)).deleteAll(any());
}

关键说明

  • 必须注入真实的MyRepository实例:这个实例是Spring Data动态生成的实现类,包含真实的数据库操作逻辑,而@SpyBean生成的是Mockito的代理,本身没有真实实现。
  • 避免直接用doCallRealMethod():对于接口类型的Spy,该方法无法找到可执行的真实方法,必然抛出你遇到的错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 06:20:52