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

时间:2015-07-20 08:48:19

标签: java spring unit-testing mockito

当尝试将Mockito与Spring一起使用时,通过bean声明创建Mock对象......

<bean id="accountMapper" class="org.mockito.Mockito" factory-method="mock"> 
    <constructor-arg value="org.example.persistence.mybatis.mappers.AccountMapper" /> 
</bean>     

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

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

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

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

我只是想在这里了解Mockito和最佳做法,因为只是因为看起来很有意义而去做一些事情似乎是一个坏主意......

2 个答案:

答案 0 :(得分:17)

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

我实际上建议不要使用Mockito.when。使用它时可能会遇到许多陷阱 - 很多情况下,当您需要其他语法时。更安全&#34;替代语法是&#34;做&#34; Mockito家族的方法。

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,那么我建议您学会使用&#34; do&#34;家庭。它们是模拟void方法的唯一方法,而Mockito文档特别提到了这一点。但只要可以使用Mockito.when,就可以使用它们。所以如果你使用&#34;做&#34;家人,你最终会在测试中保持更高的一致性,而不是学习曲线。

有关必须使用&#34; do&#34;的情况的更多信息。家人,请参阅Forming Mockito "grammars"

上的答案

答案 1 :(得分:2)

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

为了更好地检查这一点,您可以spy对象:

Bar spyBar = Mockito.spy(Bar.class)
when(spyBar.fooMethod()).then()...
实际上会调用

fooMethod()