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

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);
    }
}

错误原因分析

  1. 存根对象错误:你给workerService.get()打了存根,相当于直接mock了要测试的方法,导致真实的Service逻辑根本没执行,自然不会调用workerRepository.findById(),Mockito检测到这个不必要的存根就抛出了异常。
  2. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 14:21:23