2010-09-21 99 views
75

我試圖讓我的一個模擬對象拋出一個檢查異常,當一個特定的方法被調用。我正在嘗試以下。throw checked與Mockito的嘲諷例外

@Test(expectedExceptions = SomeException.class) 
public void throwCheckedException() { 
    List<String> list = mock(List.class); 
    when(list.get(0)).thenThrow(new SomeException()); 
    String test = list.get(0); 
} 

public class SomeException extends Exception { 
} 

但是,這會產生以下錯誤。

org.testng.TestException: 
Expected exception com.testing.MockitoCheckedExceptions$SomeException but got org.mockito.exceptions.base.MockitoException: 
Checked exception is invalid for this method! 
Invalid: com.testing.MockitoCheckedExceptions$SomeException 

望着Mockito documentation,他們只用RuntimeException,是不是可以從一個的Mockito模擬對象拋出checked異常?

回答

115

檢查Java API的List。 get(int)方法聲明爲只引發擴展RuntimeException的IndexOutOfBoundException。您試圖告訴Mockito拋出一個無效的異常,該異常將被該特定的方法調用拋出。

進一步闡明。 List接口不提供從get()方法拋出的checked Exception,這就是爲什麼Mockito失敗的原因。當你創建模擬列表時,Mockito使用List.class的定義來創建它的模擬。您使用when(list.get(0)).thenThrow(new SomeException())指定的行爲與List.class中的方法簽名不匹配,因此Mockito失敗。如果你真的想這樣做,那麼Mockito會拋出一個new RunTimeException()甚至更​​好地拋出一個new ArrayIndexOutOfBoundsException(),因爲API指定這是唯一有效的拋出異常。

+0

儘管我的真實代碼並未實際使用List,但您的答案也適用於該方法調用。我嘲笑錯誤的方法。謝謝。 – 2010-09-21 17:19:09

+2

extra:Mocktio不會抱怨如果你拋出一個沒有任何throwables的方法,但你也會得到這個異常 – dwana 2015-09-25 07:36:34

+1

對於Kotliners:Kotlin沒有檢查異常,所以你通常不能聲明(在函數簽名中)函數拋出異常。但是,您可以使用'Throws'註釋來註釋該函數,以使編譯器生成與在等效Java代碼中聲明throws相同的字節碼。有關更多詳細信息,請參見[此處](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.jvm/-throws/index.html)。 – Metallica 2017-10-04 22:58:48

2

解決方法是使用willAnswer()方法。

例如,下面的作品使用BDDMockito(而不會引發MockitoException但實際上拋出一個檢查Exception這裏需要):

given(someObj.someMethod(stringArg1)).willAnswer(invocation -> { throw new Exception("abc msg"); }); 

對於普通的的Mockito相當於將使用doAnswer方法