形成Mockito“语法”

2022-08-31 19:56:55

Mockito似乎是Java的一个非常可爱的stubbing/mocking框架。唯一的问题是我找不到任何关于使用其API的最佳方式的具体文档。测试中使用的常用方法包括:

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

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

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

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

When/Then: when(yourMethod()).thenReturn(5);

Given/Will: given(yourMethod()).willThrow(OutOfMemoryException.class);

Do/When: doReturn(7).when(yourMock.fizzBuzz());

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

Verify/Do: verify(yourMethod()).doThrow(SomeException.class);

我呛啕的是如何选择正确的方法调用模式/组合来对我的测试用例进行建模。似乎你可以以菊花链形式将这些组合在一起,似乎无穷无尽,我不确定哪种模式适合哪个问题。

一些Mockito Guru能否帮助阐明Mokito方法的哪些模式/组合用于哪些类型的测试用例(以及为什么)?提前致谢!


答案 1

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

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

我发现这些案例很难记住。因此,与其试图跟踪 和 语法何时会起作用,什么时候不起作用,我宁愿完全避免使用它们,而赞成 和 替代项。也就是说,由于您偶尔会需要 和 ,并且您始终可以使用这些方法,因此学习如何使用 和 是没有意义的。when/thenReturnwhen/thenThrowwhen/thendoReturn/whendoThrow/whendoAnswer/whendoReturn/whendoThrow/whendoAnswer/whenwhen/thenReturnwhen/thenThrowwhen/then

请注意,和 可以像 、 和 相同的方式链接在一起。他们没有的是在对 和 的单个调用中返回多个值(或引发多个异常,或运行多个答案)的选项。但我发现我很少需要这样做,这并不重要。doReturndoThrowdoAnswerthenReturnthenThrowthendoReturndoThrowdoAnswer

还有一个缺点,我认为这微不足道。您不会像使用 那样获得编译时检查其参数类型的检查。因此,如果参数类型错误,则在运行测试之前不会发现。坦率地说,我不在乎。doReturnwhen/thenReturn

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


答案 2

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+) 中不存在“given”和“will”构造

但是,在某些情况下,我希望返回值或异常响应输入。在这种情况下,可以使用 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>());

推荐