最直接表现是@mock、@mockbean或@injectmocks字段为null并抛npe;需逐层验证:①确认spring上下文是否启用,②检查是否手动new覆盖注入,③核对注解作用域与位置,④通过日志和断点验证实际注入对象。

Spring Boot 单元测试中 Mockito 注入失败,最直接的表现就是 @Mock、@MockBean 或 @InjectMocks 字段为 null,调用时抛 NullPointerException。排查不能靠猜,要按逻辑链条逐层验证。
检查测试类是否启用 Spring 上下文
Mockito 注入失败的首要原因是 Spring 容器根本没启动:
- 纯
@ExtendWith(MockitoExtension.class)不加载 Spring 配置,@Value、@Autowired、@MockBean全部失效; -
@MockBean必须配合@SpringBootTest或@ContextConfiguration才能注册进 ApplicationContext; - 若只需轻量级上下文,用
@SpringBootTest(classes = {...})显式指定必要组件,避免全量启动; - 确认测试类没有误用
@RunWith(JUnit4ClassRunner.class)(旧版)而缺失 Spring 支持。
确认依赖注入方式未被手动 new 覆盖
这是最隐蔽也最高频的错误:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 在
@Test方法里写new XxxService(),等于完全绕过 Spring 和 Mockito 的注入机制; -
@InjectMocks字段只在测试类初始化时注入一次,后续手动创建新实例不会继承 mock 依赖; - 被测类内部若存在
new操作(如工具类、策略对象),该对象的依赖也不会被自动 mock; - 控制器或服务中若用字段直接 new 实例(非构造器/Setter 注入),
@MockBean对其无效。
验证注解作用域和声明位置是否合规
注解不是写了就生效,必须满足使用前提:
-
@MockBean只对 Spring 管理的 Bean 生效,不能用于局部变量或非容器托管对象; -
@Mock和@InjectMocks需搭配@ExtendWith(MockitoExtension.class),且字段不能是private static; - 若使用 JUnit 5,
@Before已废弃,改用@BeforeEach,否则 mock 行为可能未重置; - 多个测试类共用同一上下文时,
@MockBean可能被缓存复用,导致行为污染,可加@DirtiesContext隔离。
观察日志与断点定位实际注入对象
光看代码容易误判,动手验证更可靠:
- 启动测试时开启 debug 日志:
logging.level.org.springframework.test=DEBUG,查看 ApplicationContext 是否加载了目标 Bean; - 在测试方法开头打印
System.out.println(runSummaryServiceImpl.runSummaryRepository),确认是否为 null; - 打断点进入被测方法,观察依赖字段的实际类型:是
Mockito.MockHandler实例(正确),还是原始实现类(注入失败); - 检查 IDE 的 Maven 依赖树,排除
mockito-core与mockito-inline版本冲突(常见于 PowerMock 混用场景)。










