Mockito报UnnecessaryStubbingException,Spy测试Service调用Repository失败求助
问题:测试WorkerService的get方法是否调用WorkerRepository.findById失败
想要测试WorkerService的get方法是否调用了WorkerRepository的findById方法,尝试用Spy实现但测试无法正常运行,报错信息如下:
org.mockito.exceptions.misusing.UnnecessaryStubbingException: 检测到不必要的存根。
原测试代码
@ExtendWith(MockitoExtension.class) class CrudApplicationApiApplicationTests { @Spy @InjectMocks private WorkerService workerService; @Mock private WorkerRepository workerRepository; @Test void getWorkerTest() throws Exception { Worker worker = new Worker("afsdfas", "ffeqwf1"); Mockito.when(workerService.get(4)).thenReturn(worker); Mockito.verify(workerRepository).findById(4); } }
原WorkerService代码
@Service public class WorkerService { private WorkerRepository workerRepository; @Autowired public WorkerService(WorkerRepository workerRepository) { this.workerRepository = workerRepository; } public void create(Worker worker) { workerRepository.save(worker); } public Worker get(int id) { return workerRepository.findById(id); } public List<Worker> getAll() { return workerRepository.findAll(); } public void delete(int id) { workerRepository.deleteById(id); } public void deleteByName(String name) { workerRepository.deleteWorkerByName(name); } public void update(int userId, Worker workerRequest) { Worker worker = workerRepository.findById(userId); } }
错误原因分析
- 存根对象错误:你给
workerService.get()打了存根,相当于直接mock了要测试的方法,导致真实的Service逻辑根本没执行,自然不会调用workerRepository.findById(),Mockito检测到这个不必要的存根就抛出了异常。 - Spy使用不当:这里不需要用
@Spy包装WorkerService,因为我们需要执行它的真实get方法逻辑,只需要把mock的WorkerRepository注入到真实的WorkerService实例中即可。
修正后的测试代码
@ExtendWith(MockitoExtension.class) class CrudApplicationApiApplicationTests { // 注入真实的WorkerService实例,自动关联下方的Mock对象 @InjectMocks private WorkerService workerService; @Mock private WorkerRepository workerRepository; @Test void getWorkerTest() throws Exception { int testId = 4; Worker mockWorker = new Worker("afsdfas", "ffeqwf1"); // 给依赖的Repository方法打存根,模拟返回数据 Mockito.when(workerRepository.findById(testId)).thenReturn(mockWorker); // 执行要测试的Service方法 Worker result = workerService.get(testId); // 验证Repository的findById方法是否被调用,且参数正确 Mockito.verify(workerRepository, Mockito.times(1)).findById(testId); // 可选:验证返回结果符合预期 Assertions.assertEquals(mockWorker, result); } }
修正关键点
- 移除
@Spy,使用@InjectMocks创建真实的WorkerService实例,Mockito会自动将@Mock标注的WorkerRepository注入到Service的构造方法中。 - 给
workerRepository.findById()打存根,而不是要测试的Service方法,确保Service的真实逻辑能执行。 - 先调用
workerService.get(),再执行verify验证,这样才能捕获到Repository方法的调用行为。
内容的提问来源于stack exchange,提问作者user23253016
相关产品推荐
相关产品推荐

