当尝试将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和最佳做法,因为只是因为看起来很有意义而去做一些事情似乎是一个坏主意......
答案 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()
。