You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mockito单元测试调用doNothing()触发NullPointerException问题求助

问题分析与解决方案

核心问题梳理

你遇到的错误源于几个关键的代码问题和Mockito使用误区:

  1. Mockito无法存根真实对象的方法:@InjectMocks注入的是MyService的真实实例,而非Mockito的Spy/Mock对象,doNothing()对真实对象的方法完全无效。
  2. static方法的误用:被测类中createUser是static方法,但测试中却通过实例调用,且Mockito无法直接处理static方法(除非依赖PowerMock,不推荐)。
  3. 语法与逻辑错误:
    • user.setName(Jack)中Jack未加引号,属于字符串常量语法错误;
    • 测试中调用myService.createUser()未传入User参数,导致被测方法内user为null,触发NullPointerException;
    • createUser是void方法,测试中用assertEquals接收其返回值会直接编译报错。

修正后的代码

被测服务类(MyService)

先将createUser改为实例方法(消除static,这是Mockito可测试的前提):

class MyService {
    // 去掉static修饰符,改为实例方法并返回User(适配测试断言逻辑)
    public User createUser(User user) {
        checkUserBackground(user.getName(), true);
        return user;
    }

    public void checkUserBackground(String name, Boolean newUser) {
        // 原有业务逻辑
    }
}

测试类(MyServiceTest)

使用@Spy创建可存根的真实对象包装类,替代@InjectMocks:

@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
class MyServiceTest {

    // @Spy创建真实对象的Spy包装,支持存根部分方法
    @Spy
    private MyService myService;

    @Test
    void testCreateUser() {
        User user = new User();
        user.setAge(25);
        user.setName("Jack"); // 修正:字符串常量加引号

        // 对Spy对象的checkUserBackground方法进行存根
        Mockito.doNothing().when(myService).checkUserBackground(user.getName(), true);

        // 调用实例方法并传入User参数
        User result = myService.createUser(user);
        assertEquals("Jack", result.getName());
    }
}

关键说明

  • @Spy的作用:创建真实对象的代理类,未存根的方法会执行真实逻辑,存根的方法会按Mockito配置执行(比如这里的doNothing()),完美适配你需要存根内部方法的场景。
  • static方法的处理:如果业务上必须保留createUser为static方法,需要引入PowerMock扩展,但这会增加测试复杂度,建议优先重构为实例方法,更符合面向对象设计和可测试性要求。
  • 参数传递:必须确保调用createUser时传入有效的User对象,避免空指针异常。

内容的提问来源于stack exchange,提问作者purplewind

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 20:05:25