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

Mockito测试抛出NullPointerException而非自定义ExitException问题

解决Mockito模拟CLI时出现NullPointerException的问题

看起来你在测试ApplicationRunner时遇到了预期外的NPE,而不是想要验证的ExitException。咱们一步步排查解决:

核心原因分析

最常见的问题是:你的ApplicationRunner实例没有正确关联到Mock出来的APUCLI对象,导致调用parse方法时,内部依赖的cli是null,触发了NullPointerException,根本没走到help()方法抛出自定义异常的逻辑。

解决方案步骤

1. 确保Mock实例注入到ApplicationRunner中

你需要把Mock的APUCLI关联到ApplicationRunner,有两种可靠方式:

方式1:使用@InjectMocks自动注入

Mockito会自动把@Mock标注的实例注入到@InjectMocks的对象中(支持构造器、setter或字段注入):

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.InjectMocks;
import org.mockito.MockitoAnnotations;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.doThrow;

public class ApplicationRunnerTest { 
    @Mock 
    private APUCLI cli; 

    @InjectMocks
    private ApplicationRunner runner;

    @BeforeEach
    void setUp() {
        // 初始化Mockito注解(JUnit 5+如果用MockitoExtension可省略这行)
        MockitoAnnotations.openMocks(this);
    }

    @Test
    void testParseThrowsExitExceptionOnHelpCall() {
        // 先Stub CLI的help()方法,让它抛出自定义ExitException
        doThrow(new ExitException()).when(cli).help();

        // 执行测试:触发parse方法调用help逻辑
        assertThrows(ExitException.class, () -> runner.parse(new String[]{"--help"}));
    }
}

方式2:手动构造注入(更直观)

如果ApplicationRunner有接收APUCLI的构造器,直接手动传入Mock实例:

@BeforeEach
void setUp() {
    cli = Mockito.mock(APUCLI.class);
    runner = new ApplicationRunner(cli); // 手动关联mock对象
}

2. 检查Stub语法是否正确

因为help()是void方法,不能用普通的when(...).thenThrow语法(会触发实际调用导致意外问题),必须用doThrow来Stub:

// ✅ 正确的void方法Stub方式
doThrow(new ExitException()).when(cli).help();

// ❌ 错误方式:会实际调用cli.help(),可能触发NPE或其他异常
// Mockito.when(cli.help()).thenThrow(new ExitException());

3. 验证parse方法的触发逻辑

确保当你传入触发help的参数(比如--help)时,ApplicationRunner的parse方法确实会调用cli.help()。比如你的业务逻辑应该类似:

public class ApplicationRunner {
    private final APUCLI cli;

    public ApplicationRunner(APUCLI cli) {
        this.cli = cli;
    }

    public void parse(String[] args) {
        if (Arrays.asList(args).contains("--help")) {
            cli.help(); // 这里会触发mock的Stub逻辑,抛出ExitException
        }
        // 其他业务逻辑
    }
}

额外排查点

  • 确认ExitException是非受检异常(继承自RuntimeException),如果是受检异常,parse方法需要声明抛出,否则编译报错,也会导致测试异常。
  • JUnit 5环境下,可以在测试类上添加@ExtendWith(MockitoExtension.class),替代手动调用MockitoAnnotations.openMocks(this),简化初始化流程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 08:20:17