Spring Retry最大重试次数JUnit测试用例编写问题求助
解决Spring Retry JUnit测试重试不生效的问题
你的测试没触发预期重试的核心原因很明确:Spring Retry的@Retryable注解是靠Spring AOP代理实现的,但你在测试里直接new MaxAttemptRetryService(),这个对象不是Spring容器管理的代理对象,所以注解的重试逻辑完全没被执行,自然sam()只被调用了1次。
给你两种可行的解决方案:
方案一:加载Spring上下文(推荐)
用@SpringBootTest让Spring管理bean,同时用@MockBean替换真实的Dao实现,这样就能拿到带AOP代理的服务对象,重试逻辑会正常生效:
@RunWith(SpringRunner.class) // 加载需要的类到Spring上下文,也可以直接传入你的项目主启动类 @SpringBootTest(classes = {MaxAttemptRetryService.class, MaxAttemptDao.class}) public class HystrixServiceTest { @Autowired private MaxAttemptRetryService maxAttemptRetryService; // 用@MockBean替换容器里的真实MaxAttemptDao实例 @MockBean private MaxAttemptDao maxAttemptDao; @Test(expected = Exception.class) public void testRetryMaxAttempts() throws Exception { // 配置Mock每次调用都抛出异常 when(maxAttemptDao.sam()).thenThrow(new Exception("REST服务不可用")); try { maxAttemptRetryService.retry("ll"); } finally { // 验证总共调用了3次(1次初始调用 + 2次重试) verify(maxAttemptDao, times(3)).sam(); } } }
方案二:手动创建代理(适合不想加载完整上下文的场景)
如果不想加载Spring上下文,可以手动用Spring的ProxyFactory创建带重试增强的代理对象,不过这种方式相对繁琐:
@RunWith(SpringRunner.class) public class HystrixServiceTest { private MaxAttemptRetryService maxAttemptRetryService; @Mock private MaxAttemptDao maxAttemptDao; @Before public void setUp() { // 创建原始服务对象并注入Mock的Dao MaxAttemptRetryService target = new MaxAttemptRetryService(); ReflectionTestUtils.setField(target, "maxAttemptDao", maxAttemptDao); // 手动创建代理,添加重试增强逻辑 ProxyFactory proxyFactory = new ProxyFactory(target); proxyFactory.addAdvisor(new RetryAttributeSourceAdvisor(new AnnotationAwareRetryOperationsInterceptor())); maxAttemptRetryService = (MaxAttemptRetryService) proxyFactory.getProxy(); } @Test(expected = Exception.class) public void testRetryMaxAttempts() throws Exception { when(maxAttemptDao.sam()).thenThrow(Exception.class); try { maxAttemptRetryService.retry("ll"); } finally { verify(maxAttemptDao, times(3)).sam(); } } }
额外注意事项
- 确保你的
@EnableRetry注解生效(你的服务类已经添加,这点没问题); - 重试3次后,方法会抛出最终的异常,所以测试里要么用
@expected声明预期异常,要么在try块里捕获,否则测试会因为未处理异常失败; - 不要用
@InjectMocks直接new对象,这种方式绕过了Spring的AOP代理机制,注解逻辑无法触发。
内容的提问来源于stack exchange,提问作者user2000189
相关产品推荐
相关产品推荐

