模拟第一个呼叫失败,第二个呼叫成功


119

我想使用Mockito测试下面的(简化)代码。我不知道如何告诉Mockito第一次失败,然后第二次成功。

for(int i = 1; i < 3; i++) {
  String ret = myMock.doTheCall();

  if("Success".equals(ret)) {
    log.write("success");
  } else if ( i < 3 ) {
    log.write("failed, but I'll try again. attempt: " + i);
  } else {
    throw new FailedThreeTimesException();
  }
}

我可以通过以下方式设置成功测试:

Mockito.when(myMock).doTheCall().thenReturn("Success");

以及失败测试:

Mockito.when(myMock).doTheCall().thenReturn("you failed");

但是,如何测试一次失败(或两次失败)然后成功,就可以了吗?

Answers:


250

文档

有时,对于同一方法调用,我们需要对不同的返回值/异常进行存根。典型的用例可能是模拟迭代器。Mockito的原始版本没有此功能来促进简单的模拟。例如,可以使用Iterable或简单地使用集合来代替迭代器。这些提供了自然的存根方式(例如使用真实集合)。但是,在极少数情况下,对连续调用进行存根可能会很有用:

when(mock.someMethod("some arg"))
   .thenThrow(new RuntimeException())
  .thenReturn("foo");

//First call: throws runtime exception:
mock.someMethod("some arg");

//Second call: prints "foo"
System.out.println(mock.someMethod("some arg"));

因此,在您的情况下,您需要:

when(myMock.doTheCall())
   .thenReturn("You failed")
   .thenReturn("Success");

25
这为我处理空方法的方案指明了正确的方向(感谢)-在这种情况下,您需要使用替代样式...doThrow(new RuntimeException()).doNothing().when(myMock).doTheCall();
haggisandchips

38

写你想要的最短方法是

when(myMock.doTheCall()).thenReturn("Success", "you failed");

当您提供多个thenReturn这样的参数时,每个参数将最多使用一次,最后一个参数除外,后者将根据需要使用多次。例如,在这种情况下,如果您拨打电话4次,您将获得“成功”,“失败”,“失败”,“失败”。


22

由于与此相关的评论很难阅读,因此我将添加格式化的答案。

如果尝试使用void仅引发异常的函数来执行此操作,然后执行无行为步骤,那么您将执行以下操作:

Mockito.doThrow(new Exception("MESSAGE"))
            .doNothing()
            .when(mockService).method(eq());

4

要添加到这个这个答案,你也可以使用一个循环链中的嘲笑电话。如果您需要多次模拟同一件事或以某种模式进行模拟,这很有用。

例如(尽管牵强):

import org.mockito.stubbing.Stubber;

Stubber stubber = doThrow(new Exception("Exception!"));
for (int i=0; i<10; i++) {
    if (i%2 == 0) {
        stubber.doNothing();
    } else {
        stubber.doThrow(new Exception("Exception"));
    }
}
stubber.when(myMockObject).someMethod(anyString());

我实际上不知道这个Stubber,发现它有用+1。
米海·莫尔科夫

如果您需要调用void方法,这应该是正确的答案。
db80

4

我有另一种情况,我想void为第一个调用模拟一个函数,然后在第二个调用中正常运行它。

这对我有用:

Mockito.doThrow(new RuntimeException("random runtime exception"))
       .doCallRealMethod()
       .when(spy).someMethod(Mockito.any());
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.