如何用Mockito对同时含构造注入与字段注入的类进行Mock测试
问题解答
Mockito 原生支持混合依赖注入场景,无需修改业务代码字段权限、无需手动反射操作,正确使用 @InjectMocks 即可完成所有依赖注入。
@InjectMocks 注解的实例会按照以下顺序完成依赖注入:
- 优先调用参数最多的构造方法,匹配测试类中声明的
@Mock实例完成构造注入 - 构造完成后,匹配剩余未注入的字段,自动通过反射完成私有字段注入,无需提供setter方法
SpecialClient的requestScope属性不会影响单元测试逻辑,单元测试无需启动Spring上下文,直接注入Mock实例即可。
正确测试代码示例(JUnit 5)
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; // 必须添加此注解启用Mockito注解驱动,否则所有Mockito注解不会生效 @ExtendWith(MockitoExtension.class) class MyServiceTest { @Mock ClientOne clientOne; @Mock ClientTwo clientTwo; @Mock SpecialClient specialClient; // 直接标注@InjectMocks即可,无需手动new实例 // Mockito会自动调用构造方法注入前两个依赖,再反射注入私有字段specialClient @InjectMocks MyService myService; @Test void testBizLogic() { // 此处直接调用myService的方法测试即可,三个依赖均为已初始化的mock实例,不会为null } }
JUnit 4 适配写法
如果使用JUnit4,替换注解驱动即可:
import org.junit.runner.RunWith; import org.mockito.junit.MockitoJUnitRunner; @RunWith(MockitoJUnitRunner.class) public class MyServiceTest { // 其余@Mock、@InjectMocks的声明和JUnit5完全一致 }
常见失效场景排查
如果使用@InjectMocks后specialClient仍为null,可检查以下问题:
- 未启用Mockito注解驱动,未添加
@ExtendWith(MockitoExtension.class)/@RunWith(MockitoJUnitRunner.class),也未在setup方法中调用MockitoAnnotations.openMocks(this) - 手动调用构造方法new了
MyService实例,覆盖了@InjectMocks自动生成的已完成注入的实例 SpecialClient存在多个同类型的@Mock实例,未通过@Qualifier/@Named指定匹配名称
内容的提问来源于stack exchange,提问作者ThrowableException
相关产品推荐
相关产品推荐

