2013-11-20 64 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

沒有意識到我不得不鏈接他們...... ;-) –

相關問題