Service层删除方法Mockito测试失败问题求助
我来帮你理清这个问题的核心所在——你的Service层实际调用的Repository方法,和测试代码里验证的方法根本不是同一个,这才导致了测试失败,咱们拆解来看:
问题根源
- Service层的实际操作:你的
deletePerson方法里调用的是personRepository.delete(personOptional.orElse(new Person())),这是Spring Data JPA中接收实体对象的delete(T entity)方法; - 测试代码的验证逻辑:但你在测试里写的是
Mockito.verify(personRepository, times(1)).deleteById(1l),验证的是接收ID参数的deleteById(Long id)方法。
这两个是完全独立的方法,Mockito会严格匹配方法签名,所以它会告诉你“期望的deleteById没被调用”,同时列出实际发生的两次交互:findById和delete(空Person)。
另外,你的Service逻辑还有个小问题:当personOptional为空(也就是要删除的Person不存在时),orElse(new Person())会创建一个空的Person对象并传给delete,这其实是无意义的操作——删除一个不存在的实体不会有任何数据库变更,还会导致不必要的对象创建。
解决方案
你可以根据需求选择以下两种修复方式:
方案一:修改Service层,改用deleteById(推荐)
这种方式更简洁高效,也能和你的测试逻辑匹配:
public Optional<PersonDto> deletePerson(Long id) { Assert.notNull(id, "id can't be null"); Optional<Person> personOptional = personRepository.findById(id); // 只在Person存在时执行删除,或者直接调用deleteById(id)(不存在时也不会报错) personOptional.ifPresent(p -> personRepository.deleteById(id)); // 或者直接写:personRepository.deleteById(id); return personOptional.map(p -> modelMapper.map(p, PersonDto.class)); }
修改后,你的原测试代码verify(personRepository, times(1)).deleteById(1l)就能正常通过了。
方案二:修改测试代码,匹配Service层的delete方法
如果不想改动Service逻辑,就需要调整测试来验证delete方法的调用:
@Test public void shouldDeletePersonById() { // 先mock findById的返回,模拟存在id=1的Person Person mockPerson = new Person(); mockPerson.setId(1L); when(personRepository.findById(1L)).thenReturn(Optional.of(mockPerson)); personService.deletePerson(1L); // 验证调用delete方法,传入的是我们mock的Person对象 Mockito.verify(personRepository, times(1)).delete(mockPerson); }
如果要测试Person不存在的场景,因为orElse(new Person())每次都会生成新对象,你可以用Mockito.any(Person.class)来匹配:
@Test public void shouldDoNothingWhenPersonNotFound() { when(personRepository.findById(999L)).thenReturn(Optional.empty()); personService.deletePerson(999L); Mockito.verify(personRepository, times(1)).delete(Mockito.any(Person.class)); }
额外优化建议
把Service里的personRepository.delete(personOptional.orElse(new Person()))改成personOptional.ifPresent(personRepository::delete),这样只有当Person存在时才会执行删除操作,避免无意义的空对象删除。
内容的提问来源于stack exchange,提问作者Magdalena Rumakowicz

