2011-05-18 85 views
2

我得到了以下方法:嘲諷MessageDigest.getInstance()拋出異常

private MessageDigest getMessageDigest() { 
    try { 
     return MessageDigest.getInstance("MD5"); 
    } catch (NoSuchAlgorithmException e) { 
     throw new Error(e); 
    } 
} 

得到100%的代碼覆蓋率我需要進入catch塊。但我絕對不知道我該如何做到這一點。在這種情況下是否有一些模擬框架可以幫助我?如果是這樣 - 如何?還是有另一種方式,而不必捕捉異常?

回答

2

對消息摘要getInstance方法看起來像一個靜態方法。靜態方法不能被模擬。我同意棘輪,你不應該瞄準100%的代碼覆蓋率,而是專注於測試代碼複雜的區域。

0

我會寫爲:

try { 
    return MessageDigest.getInstance("MD5"); 
} catch (NoSuchAlgorithmException e) { 
    throw (AssertionError)new AssertionError("unreachable").initCause(e); 
} 

,並宣佈由於catch塊是無法訪問,它不需要進行測試。

1

誠實地說,在這種情況下,您不需要覆蓋該代碼就無法訪問樣板文件,以確保您不必擔心用戶代碼中檢查到的異常(大多數情況下,如果可以的話,98%的覆蓋率已足夠解釋爲什麼2%錯過了)

0

您的異常無法訪問,因爲該異常永遠不會被拋出。我想這是合乎邏輯的東西,如Mockito做一個類似於:

doThrow(new NoSuchAlgorithmException()).when(MessageDigest.getInstance("MD5")); // this is psuedo code 

但它仍然沒有多大意義。你最好寫你的代碼,如:

private static final MessageDigest MD5_DIGEST; 
static { 
    try { 
     MD5_DIGEST = MessageDigest.getInstance("MD5"); 
    ///CLOVER:OFF 
    } catch (Exception e) { 
     // can't happen since MD5 is a known digest 
    } 
    ///CLOVER:ON 
} 

public MessageDigest getMessageDigest() { 
    return MD5_DIGEST; 
} 

否則,你將需要修改你的方法是可測試:

public MessageDigest getMessageDigest(String digest) throws NoSuchAlgorithmException { 
    return MessageDigest.getInstance(digest); 
} 
1

只要對此問題進行跟進,就可以通過PowerMock完成。

作爲提取物,這是我的工作代碼:

@RunWith(PowerMockRunner.class) 
@PrepareForTest({MyClass.class, MessageDigest.class}) 
public class MyClassTest { 

    private MyClass myClass = new MyClass(); 
    @Mock private MessageDigest messageDigestMock; 

    @Test 
    public void shouldDoMethodCall() throws Exception { 
     setupMessageDigest(); 

     String value = myClass.myMethodCall(); 

     // I use FestAssert here, you can use any framework you like, but you get 
     // the general idea 
     Assertions.assertThat(value).isEqualToIgnoringCase("hashed_value"); 
    } 

    public void setupMessageDigest() throws Exception { 
     PowerMockito.mockStatic(MessageDigest.class); 
     when(MessageDigest.getInstance("SHA1")).thenReturn(messageDigestMock); 
     when(messageDigestMock.digest(Matchers.<byte[]>anyObject())).thenReturn("hashed_value".getBytes()); 
    } 

} 

類 「MyClass的」 只會做這樣的事情:

public class MyClass { 

    public String myMethodCall() { 

     return new String(MessageDigest.getInstance("SHA1").digest("someString".getBytes())); 

    }   

} 

在額外的測試,你可以寫

when(MessageDigest.getInstance("SHA1")).thenThrow(new NoSuchAlgorithmException()); 

而不是我提到的回報,去你的catch塊。

但請注意,使用PowerMock有一些缺點。它通常會使用更多的內存和更多的安裝時間,因此您的測試將運行更長時間。對於這個具體的測試,它不會有很大的不同,但是就像一個人的頭。