@InjectMocks 是 Mockito 的注解,用于自动创建被测对象并按字段名或类型注入 @Mock/@Spy 依赖,不依赖 Spring 容器;需默认构造函数,支持 private 字段反射注入,但不支持 final 字段。

@InjectMocks 是 Mockito 提供的一个注解,用于在单元测试中自动创建被测对象(通常是类的实例),并把用 @Mock 或 @Spy 标记的依赖对象,按类型或名称“注入”到该对象的字段中。它不是 Spring 的注解,不依赖 Spring 容器,纯属 Mockito 的测试辅助机制。
什么时候用 @InjectMocks?
当你想测试一个类(比如 Service 类)的行为,又希望它的依赖(如 DAO、其他 Service)由 Mock 对象代替时,就可以用 @InjectMocks 创建这个被测对象,并让 Mockito 自动完成字段注入。
- 被测类必须有默认构造函数(或 Mockito 能访问到的构造方式)
- 注入基于字段(field)进行,不是通过 setter 或构造器(除非配合
MockitoSession或自定义配置) - 只对 非 final、非 static、非 private 字段尝试注入(但 private 字段也能注入,Mockito 会用反射强行设值)
基本用法示例
假设有一个 OrderService,依赖 OrderRepository 和 NotificationService:
public class OrderService {
@Autowired // 这里只是示意,实际不用 Spring 注解
private OrderRepository repository;
private NotificationService notifier;
public String createOrder(String item) {
long id = repository.save(item);
notifier.send("Order created: " + id);
return "OK";
}
}
对应测试写法:
@ExtendWith(MockitoExtension.class)
class OrderServiceTest {
@Mock
private OrderRepository repository;
@Mock
private NotificationService notifier;
@InjectMocks
private OrderService service; // Mockito 自动 new 并注入 repository & notifier
@Test
void shouldCreateOrder() {
when(repository.save("book")).thenReturn(100L);
String result = service.createOrder("book");
assertThat(result).isEqualTo("OK");
verify(notifier).send("Order created: 100");
}
}
注意:@InjectMocks 字段本身不需要手动初始化,Mockito 在测试执行前自动完成实例化和依赖填充。
常见注入失败原因和应对
如果发现字段没注入成功(比如运行时报 NullPointerException),可能是以下情况:
-
字段名不匹配:Mockito 优先按字段名匹配(如
repository字段会找名为repository的 @Mock)。若名字不同,可加@Mock(name = "xxx")显式指定 -
类型不唯一:多个 @Mock 是同一类型时,Mockito 不知道选哪个。此时需配合
@Qualifier(仅限 Mockito 4.11+)或改用@Spy+ 手动 set -
使用了 Lombok @RequiredArgsConstructor:若类只有全参构造器,
@InjectMocks可能无法实例化——建议保留无参构造器,或改用Mockito.mock(XXX.class)+ReflectionTestUtils.setField() - 字段是 final:final 字段不能被注入(即使 private),应避免在被测类中将依赖声明为 final(除非你主动用构造器注入并手动创建实例)
和 Spring @Autowired 的区别
别混淆:@InjectMocks 和 Spring 的 @Autowired 完全无关。
-
@InjectMocks是 Mockito 的反射工具,不启动 Spring 上下文,不解析 @Component/@Service - 如果要用 Spring 环境做集成测试,请用
@SpringBootTest+@MockBean,而不是@InjectMocks - 混用
@InjectMocks和@Autowired在同一个测试类中通常会导致行为不可控,不推荐
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











