如何修复 JUnit 测试中因 Mockito 注入失败导致的空指针异常

轻丽同学_1390

轻丽同学_1390

2026-07-19

811人浏览

原创

如何修复 JUnit 测试中因 Mockito 注入失败导致的空指针异常

本文详解在使用 @injectmocks 和 @spy/@mock 时,因手动 new 实例覆盖依赖注入而导致的 nullpointerexception,并提供正确配置 mockito 的完整实践方案。

本文详解在使用 @injectmocks 和 @spy/@mock 时,因手动 new 实例覆盖依赖注入而导致的 nullpointerexception,并提供正确配置 mockito 的完整实践方案。

在基于 Spring Boot 的单元测试中,常见误区是:既声明了 @InjectMocks 字段,又在测试方法内手动创建服务实例——这会导致 Spring 或 Mockito 注入的模拟对象被忽略,所有 @Autowired 的依赖(如 runSummaryRepository)保持为 null,最终在业务逻辑中调用其方法时触发 NullPointerException。

你提供的测试代码中,问题正源于这一关键错误:

@Test
public void TestprocessCustomerRunSummaries() {
    final RunSummaryServiceImpl runSummaryServiceImpl = new RunSummaryServiceImpl(); // ❌ 错误:手动 new 实例
    // ...
    runSummaryServiceImpl.processCustomerRunSummaries(runs); // 此时 runSummaryRepository == null
}

该行完全绕过了 @InjectMocks 机制,新建的对象未注入任何 mock 依赖,因此 processCustomerRunSummary() 中调用 runSummaryRepository.findByCustomerIdAndSolutionNumberAndDownloadDatetime(...) 时抛出 NPE(堆栈显示第 74 行崩溃,正是此方法内部)。

✅ 正确做法是:直接使用已由 Mockito 自动注入依赖的字段实例,无需手动构造:

@SpringBootTest
public class RunSummaryServiceImplTest {

    @Mock  // 推荐使用 @Mock 而非 @Spy,除非需部分真实行为
    private RunSummaryRepository runSummaryRepository;

    @Mock
    private FileRepository fileRepository;

    @InjectMocks
    private RunSummaryServiceImpl runSummaryServiceImpl; // ← 这个字段已被注入 mock 依赖

    @BeforeEach // 替换已废弃的 @Before(JUnit 5+)
    void setUp() {
        MockitoAnnotations.openMocks(this); // 替换已废弃的 initMocks()
    }

    @Test
    void testProcessCustomerRunSummaries() {
        // 准备测试数据
        Collection<runsummary> runs = List.of(
            new RunSummary("customer1", 1, Timestamp.valueOf("2023-05-30 10:00:00")),
            new RunSummary("customer2", 2, Timestamp.valueOf("2023-05-30 11:00:00")),
            new RunSummary("customer3", 3, Timestamp.valueOf("2023-05-30 12:00:00"))
        );

        // ✅ 直接调用已注入依赖的实例
        runSummaryServiceImpl.processCustomerRunSummaries(runs);

        // 验证行为(例如 repository 是否被调用)
        verify(runSummaryRepository, times(3))
            .findByCustomerIdAndSolutionNumberAndDownloadDatetime(anyString(), anyInt(), any(Timestamp.class));
    }
}</runsummary>

? 关键修正点总结:

  • 移除 new RunSummaryServiceImpl():这是根本原因,必须删除;
  • 统一使用 @Mock:@Spy 会创建真实对象并代理部分方法,但 RunSummaryRepository 等接口通常无实现类,@Mock 更安全、语义更清晰;
  • 升级 Mockito 初始化方式:MockitoAnnotations.initMocks(this) 已废弃,改用 MockitoAnnotations.openMocks(this)(JUnit 4/5 均适用);若使用 JUnit 5,推荐搭配 @ExtendWith(MockitoExtension.class),可省略手动初始化;
  • 命名与规范:测试方法名建议使用 camelCase(如 testProcessCustomerRunSummaries),避免 Testxxx 前缀(JUnit 不依赖命名约定);
  • 补充验证逻辑:虽 processCustomerRunSummaries 返回 void,仍可通过 verify() 断言 mock 对象是否按预期被调用,确保逻辑路径正确。

? 进阶建议:若需测试数据库交互逻辑(如 createCustomerRunSummary),应考虑使用 @DataJpaTest + H2 内存数据库进行集成测试;而纯单元测试应聚焦于服务层逻辑隔离,依赖全部 mock 化。

遵循以上实践,即可彻底规避因注入失效引发的空指针异常,构建稳定、可维护的 Mockito 单元测试。

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
软件测试常用工具
软件测试常用工具

软件测试常用工具有Selenium、JUnit、Appium、JMeter、LoadRunner、Postman、TestNG、LoadUI、SoapUI、Cucumber和Robot Framework等等。测试人员可以根据具体的测试需求和技术栈选择适合的工具,提高测试效率和准确性 。

2023.10.13

4470

8

java测试工具有哪些
java测试工具有哪些

java测试工具有JUnit、TestNG、Mockito、Selenium、Apache JMeter和Cucumber。php还给大家带来了java有关的教程,欢迎大家前来学习阅读,希望对大家能有所帮助。

2023.10.23

2861

10

Java 单元测试
Java 单元测试

本专题聚焦 Java 在软件测试与持续集成流程中的实战应用,系统讲解 JUnit 单元测试框架、Mock 数据、集成测试、代码覆盖率分析、Maven 测试配置、CI/CD 流水线搭建(Jenkins、GitHub Actions)等关键内容。通过实战案例(如企业级项目自动化测试、持续交付流程搭建),帮助学习者掌握 Java 项目质量保障与自动化交付的完整体系。

2025.10.24

1066

26

PixTV官网入口地址合集
PixTV官网入口地址合集

本专题汇总了 PixTV AI 一站式视频创作平台的官方入口与使用教程。无需下载软件,浏览器直接访问即可使用。平台将剧本、图像、视频、声音与剪辑整合在“无限画布”中,接入 GPT Image 2.5、Seedance 2.5 等头部模型。本专题整理了从新建画布、角色锚定、分镜拆分到视频生成与导出的完整操作指南,助你快速上手 AI 短剧与漫剧创作。

2026.10.10

40

15

Kratos框架HTTP与gRPC服务开发教程
Kratos框架HTTP与gRPC服务开发教程

本专题围绕Kratos框架双协议服务开发,涵盖HTTP路由与处理器编写、参数获取、gRPC服务实现与客户端调用、metadata上下文传递、encoding编解码注册、统一响应封装、超时控制与流式响应实现方法。

2026.10.10

20

15

Kratos框架Protobuf接口定义与代码生成合集
Kratos框架Protobuf接口定义与代码生成合集

本专题讲解Kratos框架接口定义体系,涵盖proto编写规范、proto add/client/server生成命令、http注解路由、validate校验、OpenAPI文档生成、跨服务proto复用与兼容性设计。

2026.10.10

0

15

C++虚函数怎么定义和调用
C++虚函数怎么定义和调用

C++虚函数是实现运行时多态的重要机制。本专题从virtual关键字的基本用法入手,介绍基类与派生类之间的函数重写、基类指针调用派生类方法,以及动态绑定的执行过程,帮助初学者掌握虚函数的核心语法。

2026.10.10

20

26

C++类与对象的封装方法教程
C++类与对象的封装方法教程

C++封装是面向对象编程的核心特性之一,通过类将数据与操作数据的函数组织在一起,并利用访问权限控制外部访问。本专题介绍类的定义、成员变量、成员函数以及public、private和protected的使用方法,帮助初学者掌握封装的基本原理。

2026.10.10

20

32

C++构造函数定义与调用方法
C++构造函数定义与调用方法

C++构造函数用于初始化类对象,是面向对象编程的重要基础。本专题从构造函数的定义、声明和调用入手,介绍默认构造函数、带参数构造函数、拷贝构造函数及成员初始化列表,帮助初学者掌握对象创建与初始化的基本方法。

2026.10.10

20

16

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.6万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 133.4万人学习