使用Mockito编写Spring单元测试时,Stub仓储层触发NPE问题排查
单元测试空指针问题排查
问题描述
- 编写仓储层Mock存根逻辑时抛出空指针异常,无法定位根因
- 当前测试无复杂业务校验需求,仅需明确异常触发原因
代码定义
仓储层接口
@Repository public interface ItemRepository extends CrudRepository<Item, String> {}
业务服务实现
@Service public class ItemService { @Autowired ItemRepository itemRepository; @Autowired SteamMarketItemService steamMarketItemService; public void addItem(Item item) { itemRepository.save(item); } public List<Item> getAllItems() { return (List<Item>) itemRepository.findAll(); } }
单元测试实现
@RunWith(MockitoJUnitRunner.class) class ItemServiceTest { @Mock ItemRepository itemRepository; @InjectMocks ItemService itemService; @Test void getAllItems_shouldReturnListOfItems() { //given List<Item> itemList = Collections.singletonList(new Item()); //when when(itemRepository.findAll()).thenReturn(itemList); List<Item> returnedItems = itemService.getAllItems(); //then Assert.assertEquals(itemList,returnedItems); } }
抛出的异常堆栈
java.lang.NullPointerException at itemServiceTest.getAllItems_shouldReturnListOfItems(ItemServiceTest.java:34) at java.base/java.util.ArrayList.forEach(ArrayList.java:1507) at java.base/java.util.ArrayList.forEach(ArrayList.java:1507) at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33) at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230) at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
根因分析
该类空指针的核心触发逻辑是Mockito的对象初始化流程未被执行,导致测试类中被@Mock、@InjectMocks修饰的字段全为null,调用方法时触发空指针。
注意:
@InjectMocks仅会自动注入测试类中已声明对应Mock类型的依赖,未声明Mock的注入字段会保持null值。由于当前测试方法未调用steamMarketItemService这类未声明Mock的字段,因此该类依赖缺失不会直接触发本次空指针异常。
常见触发场景:
- 测试框架版本混用:测试类运行在JUnit5(Jupiter)引擎下,但使用了JUnit4专属的
@RunWith(MockitoJUnitRunner.class)注解。该注解在JUnit5环境下完全不生效,不会触发Mockito的初始化逻辑,所有测试类内的依赖字段保持默认null值 - 版本不兼容:
mockito-core与junit的依赖版本存在冲突,导致Mockito runner无法正常加载执行
修复方案
- 若使用JUnit4引擎:确认依赖版本兼容,保留现有注解体系即可
- 若使用JUnit5引擎:移除
@RunWith(MockitoJUnitRunner.class)注解,替换为Mockito对应的JUnit5扩展注解@ExtendWith(MockitoExtension.class),保证mock初始化逻辑正常执行 - 补充缺失的静态依赖导入:确认导入
org.mockito.Mockito.when、对应测试框架的断言类,避免编译期通过、运行期报错的问题
内容的提问来源于stack exchange,提问作者morgenz
相关产品推荐
相关产品推荐

