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

JUnit测试类中使用Mockito时如何修复空指针异常?

JUnit测试类中使用Mockito时如何修复空指针异常?

嘿,我看了你的代码和报错栈信息,问题根源其实很清晰——你在测试方法里手动new了一个RunSummaryServiceImpl实例,完全绕开了Mockito的依赖注入机制!这个新实例里的runSummaryRepository和fileRepository都是null,调用方法时自然就触发空指针异常了。

接下来我给你一步步讲怎么修复:

第一步:移除手动实例化代码

删掉测试方法里的final RunSummaryServiceImpl runSummaryServiceImpl = new RunSummaryServiceImpl();这行代码,直接用类顶部通过@InjectMocks注解声明的那个变量就行,它已经被Mockito注入了模拟的repository依赖。

第二步:确保Mockito初始化正确

你现在用@Before里的MockitoAnnotations.initMocks(this);来初始化模拟对象是没问题的,如果是用JUnit 5,更推荐换成@ExtendWith(MockitoExtension.class)注解,这样可以省去setup方法,代码更简洁。

第三步:Stub Repository的关键方法

虽然processCustomerRunSummaries是void方法,但你需要对runSummaryRepository.findByCustomerIdAndSolutionNumberAndDownloadDatetime进行Stub——Mockito默认会返回null,不过你可以明确指定返回值,来覆盖不同的业务场景(比如返回null测试创建逻辑,返回实体测试更新逻辑)。

修改后的完整测试类代码

@SpringBootTest
// 若使用JUnit 5,替换为@ExtendWith(MockitoExtension.class),可移除下方setup方法
public class RunSummaryServiceImplTest {

    @Spy // 需保留真实方法逻辑用@Spy,仅需模拟用@Mock即可
    private RunSummaryRepository runSummaryRepository;

    @Spy
    private FileRepository fileRepository;

    @InjectMocks
    private RunSummaryServiceImpl runSummaryServiceImpl;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void testProcessCustomerRunSummaries() { // 方法名首字母小写,符合Java规范
        final Collection<RunSummary> runs = new ArrayList<>();
        runs.add(new RunSummary("customer1", 1, Timestamp.valueOf("2023-05-30 10:00:00")));
        runs.add(new RunSummary("customer2", 2, Timestamp.valueOf("2023-05-30 11:00:00")));
        runs.add(new RunSummary("customer3", 3, Timestamp.valueOf("2023-05-30 12:00:00")));

        // Stub repository方法,指定返回null,测试创建分支逻辑
        Mockito.doReturn(null)
               .when(runSummaryRepository)
               .findByCustomerIdAndSolutionNumberAndDownloadDatetime(
                   Mockito.anyString(), 
                   Mockito.anyInt(), 
                   Mockito.any(Timestamp.class)
               );

        // 使用Mockito注入的实例调用方法
        runSummaryServiceImpl.processCustomerRunSummaries(runs);

        // 验证业务逻辑是否执行:确保save方法被调用3次(每个RunSummary对应一次创建)
        Mockito.verify(runSummaryRepository, Mockito.times(3)).save(Mockito.any(RunSummaryEntity.class));
    }
}

额外说明

  • 关于@Spy和@Mock:@Mock会创建完全模拟的对象,所有方法默认返回null/空集合;@Spy会包装真实对象,默认执行真实方法,除非你Stub了特定方法。如果你的repository只是接口,用@Mock就足够了。
  • 即使方法是void类型,也可以用Mockito.verify来验证依赖方法的调用情况,确保业务逻辑符合预期。

备注:内容来源于stack exchange,提问作者shreyash

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 13:29:36