JUnit 5中Mockito重复注入Mock问题排查
解决Mockito 2.17.0 + JUnit 5.1.0 + Spring Boot 2.0.0的@InjectMocks重复注入问题
这个问题我之前踩过同款坑!本质是版本兼容性bug导致的——Mockito 2.17.0和JUnit 5.1.0搭配时,MockitoExtension在处理@InjectMocks注解时会重复执行依赖注入逻辑,最终出现你遇到的Mock被重复注入的异常行为。下面是几个靠谱的解决办法:
1. 升级Mockito到兼容版本(推荐)
Mockito在2.21.0版本修复了和JUnit 5.1.x系列的兼容问题,直接升级Mockito版本就能彻底解决这个问题:
Maven配置
在pom.xml里覆盖Spring Boot的默认Mockito版本:
<dependencyManagement> <dependencies> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <version>2.21.0</version> </dependency> <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-junit-jupiter</artifactId> <version>2.21.0</version> </dependency> </dependencies> </dependencyManagement>
Gradle配置
在build.gradle里指定Mockito版本:
ext['mockito.version'] = '2.21.0' dependencies { testImplementation 'org.mockito:mockito-junit-jupiter' }
升级后,你原来的测试代码完全不需要修改,@ExtendWith(MockitoExtension.class)的逻辑就能正常工作,不会再出现重复注入的问题。
2. 手动初始化Mock(临时方案)
如果暂时不能升级版本,可以绕过MockitoExtension,手动在测试类里初始化Mock和注入:
import org.junit.jupiter.api.BeforeEach; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; class MyServiceTest { @Mock private A a; @Mock private B b; @InjectMocks private MyService myService; @BeforeEach void setUp() { // 手动初始化Mock并完成注入 MockitoAnnotations.initMocks(this); } // 测试方法... }
这种方式能避开MockitoExtension的bug,但不如升级版本优雅,毕竟手动初始化会增加测试代码的冗余。
问题根源说明
Mockito 2.17.0的MockitoExtension在处理JUnit 5.1.0的生命周期回调时存在逻辑错误,导致@InjectMocks的注入逻辑被多次触发,最终造成Mock被重复注入到目标Bean中。后续的Mockito版本修复了这个生命周期回调的问题,所以升级是最彻底的解决方式。
内容的提问来源于stack exchange,提问作者Fabien Thouraud




