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
相关产品推荐
相关产品推荐

