在同一对象上多次调用 Mockito.时?

2022-09-04 05:29:11

当尝试将 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和这里的最佳实践,因为仅仅因为它似乎有效而使用某些东西似乎是一个坏主意......


答案 1

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

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

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”系列。它们是模拟无效方法的唯一方法,Mockito文档特别提到了这一点。但是只要可以使用它们,就可以使用它们。因此,如果您使用“do”系列,则最终将在测试中获得更多的一致性,并且学习曲线更少。Mockito.when

有关必须使用“do”系列的情况的更多信息,请参阅我在Forming Mockito“语法”上的答案


答案 2

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

要更好地检查这一点,您可以反对:spy

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

并且实际上将被调用。fooMethod()


推荐