检查方法是否仅在特定争论中被嘲笑了一次

时间:2019-05-03 08:52:34

标签: java unit-testing mockito

我在Kotlin中使用Mockito检查列表是否正确分页

我使用此代码

    logic.searchItems(filter)
    verify(vm).setItems(all.subList(0, 10), true)
    logic.loadNext()
    verify(vm).setItems(all.subList(0, 20), true)     (1)
    logic.loadNext()
    verify(vm).setItems(all.subList(0, 30), true)     (2)

从理论上讲这应该可行,但是我在(1)和(2)中得到了太多的调用异常。

如果我使用(1)中的times(1)和(2)中的times(2),则测试通过。但我希望验证是否使用这些特定参数调用了该方法。

这可以用Mockito完成吗?

2 个答案:

答案 0 :(得分:0)

经过一些测试,我发现问题是在我的逻辑中,我将结果添加到了相同的列表中,然后像这样发送回去:

addItems(results:List<Item>()){
    //verifications here
    myItems.addAll(results)
    vm.setItems(myItems,true)
}

出于某种原因,这使模仿者认为这是相同的调用?

当我这样做时,它会起作用

addItems(results:List<Item>()){
    //verifications here
    myItems.addAll(results)
    vm.setItems(myItems.map { it.copy() },true)
}

我不知道这是错误还是预期的行为,但至少可以奏效

编辑:

好吧,我觉得自己是个白痴,因为它根本不是一个bug,确实是预期的行为,并且为我节省了以后的麻烦

使用捕获程序时,我发现调用setItems方法时,Mockito会保留对返回列表的引用。

下次调用它时,我曾经将项目添加到myItems中,而Mockito保留了新的引用

但是由于我执行了addAll操作,所以以前保存的引用也得到了更新,因此,在我调用Mockito时,确实需要Mockito使用times(2)方法是很正常的,因为它的列表位于第一个调用已更新,将与第二个列表匹配。

看起来正确的方法是发送该列表的副本,以使viewModel不能以任何方式更改原始列表

答案 1 :(得分:0)

使用这种参数,作为具有特定内容的集合,我建议使用ArgumentCaptor功能。因此,您将能够捕获传递的参数,并随后使用Hamcrest或AssertJ之类的工具声明其值/状态:

final ArgumentCaptor<List> captorListOne = ArgumentCaptor.forClass(List.class);
final ArgumentCaptor<List> captorListTwo = ArgumentCaptor.forClass(List.class);
final ArgumentCaptor<List> captorListThree = ArgumentCaptor.forClass(List.class);

verify(vm).setItems(captorListOne.capture(), true)
logic.loadNext()
verify(vm).setItems(captorListTwo.capture(), true)     
logic.loadNext()
verify(vm).setItems(captorListThree.capture(), true) 

List listToAssert = captorListOne.getValue();
...

更多ArgumentCaptor