我得到了以下方法:
private MessageDigest getMessageDigest() {
try {
return MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new Error(e);
}
}
要获得100%的代码覆盖率,我需要进入catch块。但我完全不确定如何做到这一点。在这种情况下,是否有一些可以帮助我的模拟框架?如果是这样 - 怎么样?或者是否有另一种方法而不必捕捉异常?
答案 0 :(得分:2)
MessageDigest上的getInstance方法看起来像一个静态方法。静态方法不能被模拟。我同意棘手,你不应该以100%的代码覆盖为目标,而是专注于测试复杂代码的区域。
答案 1 :(得分:1)
答案 2 :(得分: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有一些缺点。它通常会使用更多的内存和更多的实例时间,因此您的测试运行时间会更长。对于这个特定的测试,它不会产生很大的不同,但只是一个头脑。
答案 3 :(得分:0)
我写这个:
try {
return MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw (AssertionError)new AssertionError("unreachable").initCause(e);
}
并声明因为catch块无法访问,所以不需要对其进行测试。
答案 4 :(得分: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);
}
答案 5 :(得分:0)
就我而言,我们的管道需要100%的覆盖率,因此我执行了以下操作:
MessageDigest
的实例catch
子句中,抛出AssertionError("unreachable", e)
表示绝对不可能到达此处jacoco.gradle
和jacocoTestReport
任务,在jacocoTestCoverageVerification
中忽略此静态类。要知道如何排除内部类,请查看我的另一篇文章:How to ignore inner static classes in Jacoco when using Gradle
(如果您使用它,它会链接到另一篇有关如何在Maven中进行操作的文章)我将方法提取到类中,因为Gradle没有一致的语法来忽略类中的成员。选中Filtering options of Jacoco和here