Mockito似乎是一个非常好的Java存根/嘲笑框架。唯一的问题是我找不到任何关于使用API的最佳方法的具体文档。测试中常用的方法包括:
doXXX(???) : Stubber
when(T) : OngoingStubbing
then(T) : OngoingStubbing
verify(???) : T
given(T) : BDDOngoingStubbing
willXXX(???) : BDDStubber
当你在实践中看到Mockito的例子时,你会看到这样的代码:
when(yourMethod()).thenReturn(5);
从我读过的所有文件中,我发现了几个";图案";Mockito的";语法;通过菊花链将这些方法调用连接在一起获得,就像上面的例子一样。我发现的一些常见模式是:
何时/然后:何时(yourMethod())。然后返回(5);
Given/Will:Given(yourMethod()).willThrow(OutOfMemoryException.class);
Do/When:doReturn(7).When(yourMock.fizhBuzz());
Will/Given/Do:willReturn(any()).gived(yourMethod()).doNothing();
Verify/Do:Verify(yourMethod()).doThrow(SomeException.class);
我所困扰的是如何选择正确的方法调用模式/组合来为我的测试用例建模。似乎你可以将这些菊花链连接在一起,形成似乎无穷无尽的组合,我不确定什么模式适合哪个问题。
Mockito的一些专家能否帮助我们了解Mockito方法的哪些模式/组合用于哪些类型的测试用例(以及为什么)?提前感谢!
when/thenReturn
、when/thenThrow
和when/then
语法有几个缺点。例如,
- 在
when/thenReturn
的情况下,如果返回类型是具有通配符,并且您希望返回相同类型的mock,则无法以避免出现编译警告 - 不能将
when/thenThrow
和when/then
用于void方法 - 你不能在Mockito间谍上使用这些语法
- 对于mock对象的每个组合,只能调用CCD_ 7一次,方法和参数,除非在mock上调用
reset
- 为mock的一个组合多次调用
when
当您使用参数匹配器时,对象和方法可能会导致问题
我发现这些案例很难记住。因此,与其试图跟踪when/thenReturn
、when/thenThrow
和when/then
语法将起作用,也不会起作用,我更喜欢完全避免它们,支持doReturn/when
、doThrow/when
和doAnswer/when
的替代方案。也就是说,由于您偶尔需要doReturn/when
、doThrow/when
和doAnswer/when
,并且您可以始终使用这些方法,因此学习如何使用when/thenReturn
、when/thenThrow
和when/then
是没有意义的。
注意,doReturn
、doThrow
和doAnswer
可以以与thenReturn
、thenThrow
和then
相同的方式链接在一起。他们没有在对doReturn
、doThrow
和doAnswer
的单个调用中返回多个值(或抛出多个异常,或运行多个应答)的选项。但我发现我很少需要这样做,所以这并不重要。
doReturn
还有一个缺点,我认为它微不足道。您不会像使用when/thenReturn
那样在编译时检查其参数的类型。因此,如果您的参数类型错误,那么在运行测试之前,您不会发现。坦率地说,我不在乎。
总之,我已经使用Mockito两年多了,我认为持续使用doReturn
、doThrow
和doAnswer
是Mockito的最佳实践。其他Mockito用户不同意。
Mockito通常有几种做事方法。
我发现自己主要使用:
// Setup expectations
when(object.method()).thenReturn(value);
when(object.method()).thenThrow(exception);
doThrow(exception).when(object.voidMethod());
// verify things
verify(object, times(2)).method();
verify(object, times(1)).voidMethod();
我发现我可以用这三种电话完成95%的任务。
另外,你使用的是什么版本的Mockito?"给定"one_answers"将要"构造在最新版本(1.9.0+)中不存在
但是,在某些情况下,我希望返回值或异常响应输入。在这种情况下,可以使用Answer接口检查方法参数并返回适当的值。
public class ReturnFirstArg<T> implements Answer<T> {
public T answer(InvocationOnMock invocation) {
return invocation.getArguments()[0];
}
}
when(object.method(7)).thenAnswer(new ReturnFirstArg<Integer>());
事实上,事情看起来比你想象的简单得多
参考:http://static.javadoc.io/org.mockito/mockito-core/2.7.12/org/mockito/Mockito.html
验证:
为了使用Mockito,您需要了解Mockito的一个基本哲学:Stubbing和Verification是分开的。因此,您提到的"Verify/Do"实际上是在做"Verification"工作,而其他4个"grammars"则用于存根。Stubbing定义了mock对象在不同情况下的反应。验证是为了确保在之前对被测系统(SUT)的调用中,mock被按预期调用。
何时/然后,给定/将:
然后是"何时"one_answers"给予"家庭。您可以简单地将它们视为彼此的别名。Mockito 1.8.x中添加了"Given"家族,使其看起来更符合BDD实践。
DoXxx:
在正常情况下,我们主要使用when(xxx).then(...)
(和given(...).will(...)
)。然而,在某些情况下,语法不起作用。最明显的情况是当存根方法的返回类型为void时。在这种情况下,when(mockObj.voidMethod()).thenThrow(anException)
不会编译。作为一种变通方法,将创建Do/When的替代语法,这样您就可以将前一行写为doThrow(anException).when(mockObj.voidMethod())