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

使用Mockito和JUnit测试void方法时报NoSuchElementException如何解决

Mockito+JUnit测试void方法抛出NoSuchElementException异常解决方案

异常根因分析

你遇到的NoSuchElementException由getById(id).get()这行代码触发:getById(id)返回的是Optional<User>类型,当内存中不存在id为2的用户时,调用Optional.get()就会直接抛出该异常。
你测试代码里虽然创建了id=2的User对象,但没有提前把这个对象存入InMemory的users存储集合里,调用删除方法时查询不到对应数据就触发了报错。

两种修复方案

方案1:测试完整真实删除逻辑(保留@Spy注解走真实InMemory方法)

需要提前把测试用的用户对象存入InMemory的存储集合,再执行删除操作,修改后测试代码如下:

@Spy
InMemory inMemoryGet;

@InjectMocks
UserService userService;

@Test
public void deleteUser(){
    // 1. 先构造测试用户并存入内存存储
    User user=new User(2L,"abed","mohamed",26);
    inMemoryGet.getUsers().put(2L, user); // 假设users是Map类型,调用对应存数据的公共方法即可
    // 2. 执行删除操作
    userService.deleteUser(2L);
    // 3. 验证方法调用
    verify(inMemoryGet,times(1)).deleteUser(2L);
}

如果InMemory没有暴露users的写入权限,也可以调用InMemory的新增用户方法提前插入数据。

方案2:仅测试UserService的调用逻辑(不需要走真实InMemory删除逻辑)

把@Spy改成@Mock,mock掉InMemory的deleteUser方法,不会执行真实的实现代码,自然不会触发查询不到的异常,修改后测试代码如下:

@Mock
InMemory inMemoryGet;

@InjectMocks
UserService userService;

@Test
public void deleteUser(){
    // 不需要提前存数据,mock的方法不会走真实实现
    userService.deleteUser(2L);
    verify(inMemoryGet,times(1)).deleteUser(2L);
}

补充说明

你当前测试用的@Spy注解默认会走被注解对象的真实方法,除非你主动打桩指定方法的返回值,所以才会触发InMemory删除方法里的真实查询逻辑。如果你的测试目标只是验证UserService是否正确调用了InMemory的删除接口,用@Mock更符合单元测试的单测边界要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 18:48:00