模拟存储库不会按预期触发

时间:2015-06-12 10:46:29

标签: spring unit-testing mocking mockito mockmvc

我使用Mockito和MockMvc进行控制器单元测试。

在POST请求之后,POSTed对象被正确解析,但我的存储库模拟没有被触发。

这是模拟代码:

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

所以这真的应该模拟对象的保存(设置ID并从中生成路径)。

不幸的是,存储库总是返回null,因此我的代码稍后在尝试将新创建的Route返回null时失败。

模拟是正确注入的,并且可以用于例如字符串比较或者如果我只检查要调用的函数,我就是不能让它在对象上触发。

上出现同样的问题
        verify(notificationRepository, times(1)).save(not);

它不会触发。

问题是: 1.)为什么模拟不会触发?我认为它不会检查对象中的值相等性,而是检查对象标识符,因为对象在序列化和反序列化之间是不相同的。

2.。)如何获得通用模拟?例如每当调用repository.save()时,无论参数如何,它总是应该执行特定的方式,例如而不是

when(notificationRepository.save(not)).thenReturn(not2);

我想要

when(notificationRepository.save()).thenReturn(not2);

P.S。如果由于某种原因你需要剩下的代码,这里是提交的部分,对象是通知的json表示(用jackson)

 mockMvc.perform(post("/api/notification").content(object)
                .contentType(MediaType.APPLICATION_JSON)
                .accept(MediaType.APPLICATION_JSON));

这里是Controller头,Object完全反序列化,值是1:1相同

 @RequestMapping(method=RequestMethod.POST)
    public ResponseEntity<?> postNotification(@RequestBody Notification n) {
        logger.debug("Saving userid "+n.getId());

感谢您的帮助。

2 个答案:

答案 0 :(得分:0)

  

1。)为什么模拟不会触发?我想它不会检查对象中的值相等性,而是检查不同的对象标识符......

默认情况下,Mockito会委托您对象的char s[]方法。如果你没有覆盖它,那么它默认检查引用。以下两行是等效的:

equals

如果具有相同字段的所有Notification对象相同,则覆盖when(notificationRepository.save(not)).thenReturn(not2); when(notificationRepository.save(not)).thenReturn(eq(not2)); // uses eq explicitly equals将使您获得所需的位置。但要注意,这可能会对Set和Map行为产生意想不到的副作用,特别是如果Notification对象在保存之前没有ID。

  

2.。)如何获得通用模拟?例如每当调用repository.save()时,无论参数如何,它总是应该执行特定的方式

使用Matchers,这非常简单:

hashCode

虽然Matchers非常强大,但要注意:他们have some tricky rules与他们的使用有关。

答案 1 :(得分:0)

对于(1),如Jeff所述,您可能需要使用eq()而不是直接引用col_1 + ' ' + col_2 = 'a b c'
对于(2)您可以使用not1
对于例如Mockito.any()
这将在模拟对象 notificationRepository 上创建存根,对于任何类型为when(notificationRepository.save(any(Notification.class))).thenReturn(not2);的参数,它总是返回not2。如果Notification方法接受Object,那么您可以编写save(),对when(notificationRepository.save(any(Object.class))).thenReturn(not2);类型的任何参数返回not2