在同一个对象上多次调用Mockito。

当试图使用Spring的Mockito时,通过bean声明创建Mock对象……

   

…在调用Mockito时我发现了一些奇怪的行为。多次没有重置Mock对象,例如:

 Mockito.when(this.accountMapper.createBadGrammarException()).thenThrow(new BadSqlGrammarException("Bla", null, new SQLException())); 

一旦在测试期间(在同一个模拟器上)多次调用此代码(“Mockito.when”),测试就会失败并出现错误(BadSqlGrammerException,即使此exception是实际预期的 – 我确实失败了如果我不抛出exception,并手动抛出它工作正常)。 这是预期的行为吗? Mockito似乎建议每次创建一个新的模拟,这意味着为每个方法创建DAO ……?

当我两次调用Mockito.when方法时到底发生了什么? 模拟应该如何反应? 替换行为? 忽略它? 不幸的是,大多数搜索仅产生如何为方法本身的多次调用返回不同结果的结果,但不会产生多次调用Mockito所期望的结果。当…

我只是想在这里了解Mockito和最佳实践,因为只是因为SEEMS才能实现,所以似乎是一个坏主意……

Mockito.when一个问题是你传递给它的参数是你试图存根的表达式。 因此,当您使用Mockito.when两次进行相同的方法调用时,第二次使用它时,您实际上将获得第一次存根的行为。

我实际上建议不要使用Mockito.when 。 使用它时可能会遇到许多陷阱 – 很多情况下,当您需要其他语法时。 “更安全”的替代语法是Mockito方法的“do”系列。

 doReturn(value).when(mock).method(arguments ...); doThrow(exception).when(mock).method(arguments ...); doAnswer(answer).when(mock).method(arguments ...); 

所以在你的情况下,你想要

 doThrow(new BadSqlGrammarException(??, ??, ??)).when(accountMapper).createBadGrammarException(); 

如果你开始使用Mockito,那么我建议你学会使用“do”系列。 它们是模拟void方法的唯一方法,而Mockito文档特别提到了这一点。 但是只要Mockito.when可以使用它们就可以使用它们。 因此,如果您使用“do”系列,您的测试结果会更加一致,而学习曲线也会减少。

有关必须使用“do”系列的案例的更多信息,请参阅我关于形成Mockito“语法”的答案

简单的答案是:
当你写Mockito.when(object.fooMethod()).then()然后实际调用fooMethod()
另一点是我们不能第一次观察它,因为它调用了模拟对象。 但是当我们第二次写的when ,我们有一些fooMethod()行为(我们先前设置它,在你的情况下是exception)。

为了更好地检查这个,你可以spy对象:

 Bar spyBar = Mockito.spy(Bar.class) when(spyBar.fooMethod()).then()... 

实际上将调用fooMethod()