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

如何用Mockito模拟Spring RetryTemplate前2次失败第3次成功?

解决Spring RetryTemplate单元测试模拟重试失败的问题

问题根源

你之前的写法完全搞反了RetryTemplate的重试触发逻辑:RetryTemplate是捕获RetryCallback中抛出的异常才会触发重试,而不是让execute方法返回异常对象。你用thenReturn(new RuntimeException())相当于让execute方法返回一个RuntimeException实例,但方法的返回类型是Stream<ClassResult>,这必然会抛出ClassCastException。

正确的Mockito写法

要模拟前两次失败、第三次成功,应该让前两次调用retryTemplate.execute()时抛出异常,第三次返回正常结果:

// 前两次调用抛出RuntimeException,触发重试
when(retryTemplate.execute(any(RetryCallback.class), any(RecoveryCallback.class)))
        .thenThrow(new RuntimeException("Error"))
        .thenThrow(new RuntimeException("Error"))
        .thenReturn(Stream.of(new ClassResult("some Data")));

注意要指定参数类型为RetryCallback.class和RecoveryCallback.class,避免匹配歧义。

用thenAnswer实现的灵活写法

如果需要根据重试次数动态控制结果,可以用thenAnswer配合计数器:

AtomicInteger attemptCount = new AtomicInteger(0);
when(retryTemplate.execute(any(RetryCallback.class), any(RecoveryCallback.class)))
        .thenAnswer(invocation -> {
            int count = attemptCount.incrementAndGet();
            if (count <= 2) {
                // 前两次抛出异常触发重试
                throw new RuntimeException("Error");
            } else {
                // 第三次返回成功结果
                return Stream.of(new ClassResult("some Data"));
            }
        });

逻辑验证

调整后的写法会和待测试代码逻辑完全匹配:

  • 第一次执行:RetryCallback抛出异常,RetryTemplate触发第一次重试
  • 第二次执行:RetryCallback再次抛出异常,RetryTemplate触发第二次重试
  • 第三次执行:RetryCallback返回正常Stream,重试流程结束,返回结果
  • 若三次都失败,才会进入RecoveryCallback逻辑返回null

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 05:40:02