如何用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
相关产品推荐
相关产品推荐

