形成Mockito“语法”

Mockito似乎是一个非常甜蜜的Java存根/模拟框架。 唯一的问题是我找不到关于使用其API的最佳方法的任何具体文档。 测试中使用的常用方法包括:

doXXX(???) : Stubber when(T) : OngoingStubbing then(T) : OngoingStubbing verify(???) : T given(T) : BDDOngoingStubbing willXXX(???) : BDDStubber 

当你在实践中看到Mockito的例子时,你会看到如下代码:

 when(yourMethod()).thenReturn(5); 

从我读过的所有文档中,我已经确定了Mockito“语法”的几个“模式”,它们是通过菊花链式连接这些方法调用获得的,就像上面的例子一样。 我发现的一些常见模式是:

当/ Then: when(yourMethod())。thenReturn(5);

给定/将:给定(yourMethod())。willThrow(OutOfMemoryException.class);

Do / When: doReturn(7).when(yourMock.fizzBu​​zz());

Will / Given / Do: willReturn(any())。given(yourMethod())。doNothing();

validation/执行:validation(yourMethod())。doThrow(SomeException.class);

我正在窒息的是如何选择正确的模式/方法调用组合来模拟我的测试用例。 看起来你可以在看似无穷无尽的组合中将它们连接起来,我不确定哪种模式适合哪个问题。

一些Mockito Guru可以帮助阐明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? “给定”和“将”结构不存在于最新版本(1.9.0+)中

但是,有些情况下我希望返回值或exception响应输入。 在这种情况下,您可以使用Answer接口检查方法参数并返回适当的值。

 public class ReturnFirstArg implements Answer { public T answer(InvocationOnMock invocation) { return invocation.getArguments()[0]; } } when(object.method(7)).thenAnswer(new ReturnFirstArg()); 

when/thenReturnwhen/thenThrowwhen/then语法有几个缺点。 例如,

  • when/thenReturn的情况下,如果返回类型是带通配符的generics,并且您希望返回相同类型的模拟,则无法避免编译警告。
  • 你不能使用when/thenThrowwhen/then使用void方法。
  • 你不能在Mockito间谍上使用这些语法。
  • 除非在mock上调用reset ,否则只能when模拟对象,方法和参数的每个组合调用一次。
  • 当您使用参数匹配器时,多次为模拟对象和方法的一个组合调用可能会导致问题。

我发现这些案件很难记住。 所以我没有试图跟踪when/thenReturnwhen/thenThrowwhen/then语法何时会发生和不起作用,我宁愿完全避免它们,而是支持doReturn/whendoThrow/whendoAnswer/when替代品。 也就是说,因为你偶尔需要doReturn/whendoThrow/whendoAnswer/when ,并且你总是可以使用这些方法,学习如何使用when/thenReturnwhen/thenThrowwhen/then

请注意, doReturndoThrowdoAnswer可以以与doAnswer相同的方式链接在一起, thenthenReturnthen 。 他们没有的是在一次调用doReturndoThrowdoAnswer返回多个值(或抛出几个exception,或运行几个答案)的doAnswer 。 但我发现我很少需要这样做,这并不重要。

doReturn还有一个缺点,我认为这是不重要的。 您没有得到编译时检查其参数的类型,就像使用when/thenReturn 。 因此,如果您的参数类型错误,则在运行测试之前不会发现。 坦率地说,我不在乎。

总而言之,我已经使用Mockito超过两年了,我认为doReturndoThrowdoAnswer的一致使用是Mockito的最佳实践。 其他Mockito用户不同意。

事实上事情看起来比你想象的要简单得多

参考: http : //static.javadoc.io/org.mockito/mockito-core/2.7.12/org/mockito/Mockito.html

validation

为了使用Mockito,您需要了解Mockito的一个基本哲学:Stubbing和Verification是分开的。 因此,您提到的“validation/执行”实际上正在执行“validation”工作,而其他4个“语法”则用于存根。 Stubbing定义模拟对象在不同情况下的反应方式。 validation是在先前对被测系统(SUT)的调用中确保按预期调用模拟的内容。

当/然后,给定/将

然后它来到“何时”和“给定”的家庭。 您可以简单地将它们视为彼此的别名。 “给定”系列在Mockito 1.8.x中添加,以使其看起来更符合BDD实践。

DoXxx

在正常情况下,我们主要使用when(xxx).then(...) (和given(...).will(...) )。 但是有些情况下语法不起作用。 最明显的情况是当存根方法的返回类型为空时。 在这种情况下when(mockObj.voidMethod()).thenThrow(anException)不会编译。 作为一种解决方法,创建了Do / When的替代语法,因此您可以将前一行写为doThrow(anException).when(mockObj.voidMethod())