Java Mockito中的连续调用测试

Java Mockito中的连续调用测试,java,junit,mockito,Java,Junit,Mockito,我有简单的服务 包net.betlista; 导入java.util.List; 公共类MyServiceImpl实现了MyService{ MyDao道; 公共无效保存所有最终列表{ 对于最终int i:列表{ dao.savei; } } void setdao最终MyDao dao{ this.dao=dao; } } 和刀 包net.betlista; 公共类MyDaoImpl实现MyDao{ 公共void保存最终整数i{ //什么都不做,可以测试吗 } } 我想用Mockito测试一下

我有简单的服务

包net.betlista; 导入java.util.List; 公共类MyServiceImpl实现了MyService{ MyDao道; 公共无效保存所有最终列表{ 对于最终int i:列表{ dao.savei; } } void setdao最终MyDao dao{ this.dao=dao; } } 和刀

包net.betlista; 公共类MyDaoImpl实现MyDao{ 公共void保存最终整数i{ //什么都不做,可以测试吗 } } 我想用Mockito测试一下,当我调用service.saveAll时,会对列表中的所有实例调用save调用:

包net.betlista; 导入java.util.LinkedList; 导入java.util.List; 导入org.junit.Test; 导入org.mockito.inoorder; 导入org.mockito.mockito; 公共类MyServiceTest{ @试验 公共空隙试验{ 最终mydaomock=Mockito.mockMyDao.class; 最终MyServiceImpl服务=新的MyServiceImpl; service.setdaomock; 最终列表=新链接列表; 表1.add1; 表1.add2; service.saveAlllist; //不工作,没关系,应该会失败 //Mockito.verifydaoMock.saveMatchers.eq1; //Mockito.verifydaoMock.saveMatchers.eq1; final inoorder inoorder=Mockito.inordaomock; inOrder.verifydaoMock.save1; inOrder.verifydaoMock.save1;//将1更改为2以修复测试 Mockito.verifydaoMock; } } 注释部分不工作=通过,但应失败

使用InOrder可以工作,但事实上我对顺序不感兴趣,例如,如果使用set而不是list,则顺序未知

有什么想法吗,或者我只是想做些没意义的事

我想用Mockito测试一下,当我调用service.saveAll时,列表中的所有实例都会调用save调用

好的,那么这个怎么样:

service.saveAll(list);

for (int i:list)
{
    Mockito.verify(daoMock).save(Matchers.eq(i));
}
我不完全确定你为什么认为注释掉的行应该失败,但我猜这是因为你想确保它只被调用一次?如果是这样,那么它通过它的原因是因为它只被调用过一次,然而,您的测试代码正在两次验证它只被调用过一次,这没有多大用处。上面的代码将验证是否对列表中的每个项目调用了save方法一次,并且只调用了一次

 Mockito.verify(daoMock, Mockito.times(2)).save(Matchers.eq(1));
由于要验证相同的值,请使用时间

但是,测试是否有您想要的调用次数的更好方法是使用verifyNoMoreInteractions

所以测试是这样的:

 verify(daoMock).save(1);
 verify(daoMock).save(2);
 verifyNoMoreInteractions(daoMock);

最好的方法是找一个辩手


ArgumentCaptor允许您访问曾经传递给此方法的所有值。所以不必担心这个方法是否被额外调用了;如果相同的值在原始列表中出现两次,则没有问题。

注意,在注释的代码中,OP测试了1次。循环不会解决此问题。为True,但OP出于某种原因试图在两次调用1进行验证时使测试失败。两次使用verify1不会导致测试按照OP的要求失败。是的,但我的观点是,两次调用verify1是一件不明智的事情,很可能是对可能有效的测试条件的错误实现。它相当于调用assertEquals。。。假设没有副作用,连续两次调用verify1。好吧,我不知道两次调用verify1是同一个断言。当添加Mockito.verifynomore交互daomock时,测试应该失败;在for循环之后。如果1在列表中出现两次,那么上面的代码将故意失败,因为我们明确表示,我们期望使用1作为参数进行一次且仅一次调用。如果我们期望有多个以1为参数的调用,那么我们需要重新构造期望/验证:例如verifydaoMock、times2.save1或verifydaoMock,至少1.save1这是一个很好的答案。从长远来看,OP可能应该采用循环模式,如.Concur,循环是goMockito.verifydaoMock、Mockito.times2.save1的方式;更具可读性-不需要参数匹配器。这一切都取决于测试真正想要实现的目标。在很多情况下,测试一个特定参数只调用一次方法是很重要的。如果save是对数据库的密集调用,那么如果我们对数据库进行了冗余调用,那么测试失败就更好了。不,@ChrisKnight我想你可能误解了我。您可以在此测试之后检查values.getAllValues。您可以查看其中是否存在冗余调用,因为冗余的定义是合适的。这实际上意味着您将直接从列表中进行详细的验证,而不是通过一系列调用来验证。在任何情况下,它都更灵活、更强大。好吧,我给你一些灵活性,但我认为对于简单的情况,它可读性较差。我宁愿在s中使用Mockito的简单意图揭示API
我还发现这种方法对于需要检查数千个具有不同参数的调用的情况非常有用。检查常规“for”循环是否需要花费不合理的时间
service.saveAll(list);

ArgumentCaptor<Integer> values = ArgumentCaptor.forClass(Integer.class);
verify(daoMock, times(list.size())).save(values.capture());
assertEquals(list, values.getAllValues());