JUnit+Spring测试中Optional.get()抛出NoSuchElementException的解决方法
解决JUnit测试中Optional.get()导致的NoSuchElementException问题
这个问题我之前也碰到过,核心就是Optional的get()方法太“苛刻”——只要里面没值就直接抛出NoSuchElementException,完全不给缓冲的机会。咱们直接通过isPresent()方法做前置检查来修复:
问题根源
你的代码里jobTitleRepository.findById(id).get()这一步,当数据库中不存在对应id的记录时,findById会返回一个空的Optional,此时直接调用get()就会触发异常,这就是JUnit测试失败的原因。
修复后的代码
public Job theID(Integer id) { if(id == null) { throw new IllegalArgumentException("Id is missing."); } // 先获取Optional对象,避免重复调用数据库查询 Optional<JobEntity> jobEntityOpt = jobTitleRepository.findById(id); // 用isPresent()检查Optional中是否有值 if(jobEntityOpt.isPresent()) { // 确认有值后再调用get(),安全无异常 return jobTitleMapper.entityToModel(jobEntityOpt.get()); } else { // 这里根据业务需求处理无值场景,推荐抛出明确的异常 throw new RuntimeException("Job with id " + id + " not found"); // 如果业务允许返回null,也可以写:return null; } }
测试方法适配
你的findId测试方法可以分成两种场景来覆盖:
- 场景1:存在的ID:调用
theID方法后,断言返回的Job对象的属性与预期一致 - 场景2:不存在的ID:用
assertThrows断言方法会抛出你定义的异常(比如上面的RuntimeException,或者自定义的JobNotFoundException),这样测试就能覆盖所有情况,顺利通过
额外优化建议
其实除了isPresent(),还可以用Optional的其他方法让代码更简洁,比如orElseThrow:
public Job theID(Integer id) { if(id == null) { throw new IllegalArgumentException("Id is missing."); } // 一行代码完成检查+取值+异常抛出 JobEntity jobEntity = jobTitleRepository.findById(id) .orElseThrow(() -> new RuntimeException("Job with id " + id + " not found")); return jobTitleMapper.entityToModel(jobEntity); }
这种写法更符合Java 8+的函数式风格,代码更紧凑,效果和用isPresent()检查是一样的。
内容的提问来源于stack exchange,提问作者starlord
相关产品推荐
相关产品推荐

