如何正确测试保存对象并返回ID的Service方法?
问题分析
你当前测试失败的核心原因是:Service方法内部是自行创建NewObject实例的,你mock的newObjectmock并没有被Service使用。虽然你让repository.save()返回了这个mock对象,但Service里始终用的是它一开始创建的那个NewObject实例,而这个实例的id并没有被设置,所以返回null。
正确测试方案
针对这种场景,有两种常用的解决方式:
方式一:使用Mockito Answer 修改Service创建的对象ID
通过Answer接口,在repository.save()被调用时,直接修改传入的NewObject实例的id,这样Service里的对象就能拿到正确的id值:
@Test void addNotification() { // 当repository.save被调用时,修改传入的NewObject的id为1L when(repository.save(any(NewObject.class))).thenAnswer(invocation -> { NewObject actualObject = invocation.getArgument(0); actualObject.setId(1L); // 假设NewObject有setId方法 return actualObject; }); // 调用Service方法 long resultId = service.addNotification(new ObjectWithInformation()); // 验证结果 assertEquals(1L, resultId); verify(repository).save(any(NewObject.class)); verify(repository).flush(); }
方式二:Spy真实的NewObject实例(如果NewObject是简单POJO)
如果NewObject是普通的POJO类,可以用spy来包装真实实例,让getId()返回指定值,同时确保Service里的对象是这个spy实例:
@Test void addNotification() { // 创建真实NewObject的spy实例 NewObject spyObject = spy(new NewObject()); doReturn(1L).when(spyObject).getId(); // 需确保Service创建的是这个spyObject,可通过调整依赖注入实现,比如构造注入 when(repository.save(eq(spyObject))).thenReturn(spyObject); long resultId = service.addNotification(new ObjectWithInformation()); assertEquals(1L, resultId); }
关键注意点
- 不要试图mock Service内部new出来的对象,除非使用PowerMock(不推荐,会增加测试复杂度)。
- 优先使用
Answer来修改传入的真实对象,这种方式更贴近真实业务逻辑,测试也更可靠。
内容的提问来源于stack exchange,提问作者User69
相关产品推荐
相关产品推荐

