Spring Boot Kotlin中@Retryable下无法Mock第三方Final类的测试问题
解决Spring Retry与Mockito Inline Mock的冲突问题
这问题我之前在项目里也踩过坑,本质是Spring的CGLIB重试代理和Mockito的inline Mock模式之间的兼容性冲突,我来给你一步步拆解原因和解决方案:
问题根源
当你同时启用@EnableRetry和引入mockito-inline时,会出现两个关键冲突点:
@EnableRetry会让Spring通过CGLIB为带有@Retryable的MyService生成代理类,用来实现重试逻辑;mockito-inline替换了Mockito默认的CGLIB MockMaker为inline实现,导致@SpyBean无法正确把Mockito的Spy包装到Spring的CGLIB代理实例上——这就是为什么你调用verify(myService)时会报错“不是mock对象”。
而当你移除其中一个依赖/注解时,冲突消失,测试自然就能通过,但这显然无法满足同时测试重试和mock final类的需求。
解决方案
我们可以调整测试方式,既保留Spring的重试代理,又能正常mock final类和验证方法调用:
方案1:调整测试类配置,兼容Spring代理与Mockito Spy
直接注入Spring代理后的MyService,在需要验证方法调用时手动用Mockito Spy包装它,这样既能保留重试逻辑,又能让Mockito识别对象:
@RunWith(SpringRunner::class) @EnableRetry class TTest { @MockBean lateinit var restClient: RestClient // 注入Spring生成的带重试代理的MyService实例 @Autowired lateinit var myService: MyService @Test fun `should throw exception and trigger retry`() { // 借助mockito-inline mock final异常类 val notFoundException = mock<HttpClientErrorException.NotFound>() whenever(restClient.getAllData()).thenThrow(notFoundException) // 验证调用时抛出目标异常 assertThrows<HttpClientErrorException.NotFound> { myService.makeRestCall() } // 核心验证:重试逻辑生效,总共调用3次RestClient方法 verify(restClient, times(3)).getAllData() } @Test fun `makeRestCall should be invoked`() { // 手动将Spring代理实例包装为Mockito Spy val spiedService = Mockito.spy(myService) spiedService.makeRestCall() // 现在可以正常验证方法调用了 verify(spiedService).makeRestCall() } }
方案2:优化依赖版本(可选)
建议把mockito-inline的版本升级到更稳定的版本(比如3.12.4及以上),避免旧版本和Spring的CGLIB代理之间的潜在兼容性问题:
<dependency> <groupId>org.mockito</groupId> <artifactId>mockito-inline</artifactId> <version>3.12.4</version> <scope>test</scope> </dependency>
方案3:更合理的测试策略(推荐)
其实验证myService.makeRestCall()是否被调用的测试意义不大,重试功能的核心测试目标应该是验证重试逻辑是否生效——比如验证restClient.getAllData()被调用了3次(对应你设置的maxAttempts = 3),这也是方案1中第一个测试的核心逻辑。
为什么这个方案能解决问题?
- 直接注入Spring代理的
MyService保证了@Retryable的重试逻辑正常生效; - 手动用
Mockito.spy()包装Spring代理实例,让Mockito能够识别并验证方法调用; mockito-inline依然可以正常处理HttpClientErrorException.NotFound这类final类的mock需求。
内容的提问来源于stack exchange,提问作者a3dsfcv
相关产品推荐
相关产品推荐

