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

Flo*_*etz 8 java spring unit-testing mockito

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

<bean id="accountMapper" class="org.mockito.Mockito" factory-method="mock"> 
    <constructor-arg value="org.example.persistence.mybatis.mappers.AccountMapper" /> 
</bean>     
Run Code Online (Sandbox Code Playgroud)

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

Mockito.when(this.accountMapper.createBadGrammarException()).thenThrow(new BadSqlGrammarException("Bla", null, new SQLException()));
Run Code Online (Sandbox Code Playgroud)

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

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

我只是想在这里了解Mockito和最佳实践,因为只是因为它看起来很有效,所以选择一些东西似乎是一个坏主意......

Daw*_*ica 22

其中一个问题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 ...);
Run Code Online (Sandbox Code Playgroud)

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

doThrow(new BadSqlGrammarException(??, ??, ??)).when(accountMapper).createBadGrammarException();
Run Code Online (Sandbox Code Playgroud)

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

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