模拟第一次通话失败,第二次通话成功

问题描述:

我想使用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"); 

但我怎么能测试,如果失败一次(或两次),然后成功了,没关系?

+0

任何一个可以解释如何实现使用Jmockito相同 – Bharat 2018-02-06 14:15:01

the docs

有时候我们需要用不同的返回值/异常的同样的方法调用存根。典型的用例可能是嘲讽迭代器。原始版本的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"); 
+0

嘿,这真棒,谢谢乔恩。 – vikingsteve 2013-03-13 12:21:08

+9

这指出我在正确的方向(谢谢)我的方案是处理无效方法 - 在这种情况下,您需要使用替代的风格...... dothrow(new RuntimeException())。doNothing()。when(myMock ).doTheCall();' – haggisandchips 2016-09-13 15:04:05

最短的方式来写你想要的是

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

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

由于与此相关的评论很难阅读。我会添加一个格式化的答案。

如果您试图用void函数来做到这一点。你可能想要一个异常而不是行为。然后,你会做这样的事情:

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

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

EG(虽然牵强的一个):

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());