Spring Retry测试时重试次数比配置多1次,求问题排查及测试方案
问题1:测试调用次数不匹配的原因
- 多余的启动自动调用
你给FakeConfiguration实现了ApplicationRunner接口,在@SpringBootTest启动Spring上下文时,会自动执行run()方法触发runParser()的重试逻辑,此时你的Mock已经生效,这一步就已经调用了5次add()方法;后续你在测试方法中手动调用fakeConfiguration.runParser()又触发了1次调用,总次数正好是报错中的6次。 - 注解使用位置不规范
不要将@Retryable标注在@Configuration配置类的方法上,配置类本身是通过CGLIB代理实现的,容易和Spring Retry的AOP代理逻辑产生冲突,重试逻辑建议放到独立的@Component/@Service类中。 - 参数说明补充
@Retryable的maxAttempts参数本身包含第一次正常调用,配置为5就是1次初始调用+4次重试,总共调用5次,这个参数定义是符合你的预期的。
问题2:Spring Retry的测试方式说明
声明式注解(@Retryable)场景
这类重试逻辑基于Spring AOP代理实现,必须由Spring上下文管理Bean生成代理对象才能生效,因此需要启动Spring上下文,属于集成测试范畴。
编程式RetryTemplate场景
如果不想启动Spring上下文做单元测试,可以直接使用编程式的RetryTemplate,手动配置重试规则后直接调用,不需要依赖Spring容器,可直接在普通单元测试中验证重试逻辑。
修复后的代码示例
1. 把重试逻辑移到独立服务类
@Service public class ParserService { private final FakeParser fakeParser; public ParserService(FakeParser fakeParser) { this.fakeParser = fakeParser; } @Retryable(maxAttempts = 5, value = RuntimeException.class) public void runParser() { fakeParser.add(); } }
2. 调整配置类
@Configuration @EnableRetry public class FakeConfiguration { // 去掉ApplicationRunner实现,避免启动时自动调用重试逻辑 }
3. 调整测试类
@RunWith(SpringRunner.class) @SpringBootTest class SpringtestApplicationTests { @Autowired private ParserService parserService; @MockBean private FakeParser fakeParser; @Test public void retry5times(){ when(fakeParser.add()).thenThrow(RuntimeException.class); try { parserService.runParser(); } catch (RuntimeException e){ // 忽略预期异常 } verify(fakeParser, times(5)).add(); // 验证通过 } }
无Spring上下文的单元测试示例(编程式RetryTemplate)
public class RetryUnitTest { @Test public void testRetryWithoutSpring() { FakeParser fakeParser = Mockito.mock(FakeParser.class); when(fakeParser.add()).thenThrow(RuntimeException.class); // 手动配置重试规则 RetryTemplate retryTemplate = RetryTemplate.builder() .maxAttempts(5) .retryOn(RuntimeException.class) .build(); try { retryTemplate.execute(context -> { fakeParser.add(); return null; }); } catch (RuntimeException e) { // 忽略预期异常 } verify(fakeParser, times(5)).add(); // 验证通过 } }
内容的提问来源于stack exchange,提问作者davecall
相关产品推荐
相关产品推荐

