模拟存储库未按预期触发
Mocked repository does not trigger as expected
我使用 Mockito 和 MockMvc 进行了控制器单元测试。
在 POST 请求后,POSTed object 被正确解析,但我的存储库模拟没有被触发。
这是模拟代码:
Date mydate = new Date();
Notification not = new Notification();
not.setId(-1L);
not.setUserid("BaBlubb");
not.setTimestamp(mydate);
not.setContent("MyContent");
Notification not2 = new Notification();
not2.setId(1L);
not2.setUserid("BaBlubb");
not2.setTimestamp(mydate);
not2.setContent("MyContent");
when(notificationRepository.save(not)).thenReturn(not2);
所以这真的应该模拟 object 的保存(设置 ID 并从中生成路由)。
不幸的是,存储库始终 return 为 null,因此我的代码后来在尝试 return 从 null 中创建新路由时失败。
mocks 被正确注入并且可以工作,例如。字符串比较或者如果我只检查函数是否被调用,我就是无法让它在 Objects.
上触发
同样的问题发生在
verify(notificationRepository, times(1)).save(not);
不触发。
问题是:
1.) 为什么模拟不触发?我想它不会检查 object 中的值是否相等,但会检查 object 标识符,因为 object 是序列化的,而 de-serialized 是不一样的。
2.) 如何获得通用模拟?例如每当 repository.save() 被调用时,无论参数如何,它总是应该执行特定的方式,例如而不是
when(notificationRepository.save(not)).thenReturn(not2);
我想要
when(notificationRepository.save()).thenReturn(not2);
P.S。如果出于某种原因您需要其余代码,这里是提交的部分,object 是通知的 json 表示(使用 jackson)
mockMvc.perform(post("/api/notification").content(object)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON));
这里是控制器 header,Object 完美 de-serialized,值 1:1 相同
@RequestMapping(method=RequestMethod.POST)
public ResponseEntity<?> postNotification(@RequestBody Notification n) {
logger.debug("Saving userid "+n.getId());
感谢您的帮助。
1.) Why does the mock not trigger? I suppose it does not check for value equality in the object, but for object identifiers, which are not the same...
默认情况下,Mockito 委托给对象的 equals
方法。如果您没有覆盖它,那么默认情况下它会检查引用。下面两行是等价的:
when(notificationRepository.save(not)).thenReturn(not2);
when(notificationRepository.save(not)).thenReturn(eq(not2)); // uses eq explicitly
如果具有相同字段的所有通知对象都相同,那么覆盖 equals
和 hashCode
将使您到达需要去的地方。但是请注意,这可能会对 Set 和 Map 行为产生意想不到的副作用,尤其是当您的 Notification 对象在保存之前没有 ID 时。
2.) How can I get a generic mock? e.g. whenever repository.save() is called, no matter the parameter, it always should perform a specific way
使用 Matchers,这非常简单:
when(notificationRepository.save(not)).thenReturn(any(Notification.class));
尽管 Matchers 非常强大,但请注意:它们 have some tricky rules 与它们的使用相关联。
对于 (1),如 Jeff 所述,您可能需要使用 eq() 而不是直接引用 not1
对于 (2) 您可以使用 Mockito.any()
例如when(notificationRepository.save(any(Notification.class))).thenReturn(not2);
这将在模拟对象 notificationRepository 上创建存根,对于 Notification
类型的任何参数,它总是 return not2
。如果 save()
方法接受 Object 那么你可以写 when(notificationRepository.save(any(Object.class))).thenReturn(not2);
这将 return not2
用于 Object
类型的任何参数
我使用 Mockito 和 MockMvc 进行了控制器单元测试。
在 POST 请求后,POSTed object 被正确解析,但我的存储库模拟没有被触发。
这是模拟代码:
Date mydate = new Date();
Notification not = new Notification();
not.setId(-1L);
not.setUserid("BaBlubb");
not.setTimestamp(mydate);
not.setContent("MyContent");
Notification not2 = new Notification();
not2.setId(1L);
not2.setUserid("BaBlubb");
not2.setTimestamp(mydate);
not2.setContent("MyContent");
when(notificationRepository.save(not)).thenReturn(not2);
所以这真的应该模拟 object 的保存(设置 ID 并从中生成路由)。
不幸的是,存储库始终 return 为 null,因此我的代码后来在尝试 return 从 null 中创建新路由时失败。
mocks 被正确注入并且可以工作,例如。字符串比较或者如果我只检查函数是否被调用,我就是无法让它在 Objects.
上触发同样的问题发生在
verify(notificationRepository, times(1)).save(not);
不触发。
问题是: 1.) 为什么模拟不触发?我想它不会检查 object 中的值是否相等,但会检查 object 标识符,因为 object 是序列化的,而 de-serialized 是不一样的。
2.) 如何获得通用模拟?例如每当 repository.save() 被调用时,无论参数如何,它总是应该执行特定的方式,例如而不是
when(notificationRepository.save(not)).thenReturn(not2);
我想要
when(notificationRepository.save()).thenReturn(not2);
P.S。如果出于某种原因您需要其余代码,这里是提交的部分,object 是通知的 json 表示(使用 jackson)
mockMvc.perform(post("/api/notification").content(object)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON));
这里是控制器 header,Object 完美 de-serialized,值 1:1 相同
@RequestMapping(method=RequestMethod.POST)
public ResponseEntity<?> postNotification(@RequestBody Notification n) {
logger.debug("Saving userid "+n.getId());
感谢您的帮助。
1.) Why does the mock not trigger? I suppose it does not check for value equality in the object, but for object identifiers, which are not the same...
默认情况下,Mockito 委托给对象的 equals
方法。如果您没有覆盖它,那么默认情况下它会检查引用。下面两行是等价的:
when(notificationRepository.save(not)).thenReturn(not2);
when(notificationRepository.save(not)).thenReturn(eq(not2)); // uses eq explicitly
如果具有相同字段的所有通知对象都相同,那么覆盖 equals
和 hashCode
将使您到达需要去的地方。但是请注意,这可能会对 Set 和 Map 行为产生意想不到的副作用,尤其是当您的 Notification 对象在保存之前没有 ID 时。
2.) How can I get a generic mock? e.g. whenever repository.save() is called, no matter the parameter, it always should perform a specific way
使用 Matchers,这非常简单:
when(notificationRepository.save(not)).thenReturn(any(Notification.class));
尽管 Matchers 非常强大,但请注意:它们 have some tricky rules 与它们的使用相关联。
对于 (1),如 Jeff 所述,您可能需要使用 eq() 而不是直接引用 not1
对于 (2) 您可以使用 Mockito.any()
例如when(notificationRepository.save(any(Notification.class))).thenReturn(not2);
这将在模拟对象 notificationRepository 上创建存根,对于 Notification
类型的任何参数,它总是 return not2
。如果 save()
方法接受 Object 那么你可以写 when(notificationRepository.save(any(Object.class))).thenReturn(not2);
这将 return not2
用于 Object