2013-11-20 61 views
7

下面的代码:如何让Mockito模拟按顺序执行不同的操作?

ObjectMapper mapper = Mockito.mock(ObjectMapper.class); 
    Mockito.doThrow(new IOException()).when(mapper).writeValue((OutputStream) Matchers.anyObject(), Matchers.anyObject()); 
    Mockito.doNothing().when(mapper).writeValue((OutputStream) Matchers.anyObject(), Matchers.anyObject()); 

    try { 
     mapper.writeValue(new ByteArrayOutputStream(), new Object()); 
    } catch (Exception e) { 
     System.out.println("EXCEPTION"); 
    } 

    try { 
     mapper.writeValue(new ByteArrayOutputStream(), new Object()); 
    } catch (Exception e) { 
     System.out.println("EXCEPTION"); 
    } 

预期输出是

EXCEPTION

吧?

但我什么也没得到

如果我那么做doThrow的doNothing后,我得到

EXCEPTION
EXCEPTION

所以它看起来是最后的模拟是被采取的那个...我想它会按照他们注册的顺序进行模拟。

我期待产生一个模拟抛出异常第一时间与正常完成,第二次......

回答

15

可以的Mockito连续存根行为具有相同的参数,永远重复最后的指令,但是他们都有成为同一“链条”的一部分。否则,Mockito会认为你已经改变了主意并覆盖了以前的模拟行为,如果你已经在setUp@Before方法中建立了良好的默认值并且想要在特定的测试用例中覆盖它们,这并不是一个坏的功能。

为“这接下来会发生作用的Mockito”的一般规则:最近最常定义的所有参数匹配链将被选中。在链中,每个动作都会发生一次(如果像thenReturn(1, 2, 3)那样给出多个thenReturn值),那么最后一个动作将永久重复。

// doVerb syntax, for void methods and some spies 
Mockito.doThrow(new IOException()) 
    .doNothing() 
    .when(mapper).writeValue(
     (OutputStream) Matchers.anyObject(), Matchers.anyObject()); 

这是更为常见的when语法链thenVerb语句,你正确地避免在这里为您void方法是等效的:

// when/thenVerb syntax, to mock methods with return values 
when(mapper.writeValue(
     (OutputStream) Matchers.anyObject(), Matchers.anyObject()) 
    .thenThrow(new IOException()) 
    .thenReturn(someValue); 

注意,您可以使用静态进口Mockito.doThrowMatchers.*,并切换为any(OutputStream.class)而不是(OutputStream) anyObject(),并用此结束:

// doVerb syntax with static imports 
doThrow(new IOException()) 
    .doNothing() 
    .when(mapper).writeValue(any(OutputStream.class), anyObject()); 

请参阅Mockito's documentation for Stubber了解可链接的命令的完整列表。

+1

没有意识到我不得不链接他们...... ;-) –

相关问题