模拟 MessageDigest.getInstance() 抛出异常
我得到了以下方法:
private MessageDigest getMessageDigest() {
try {
return MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new Error(e);
}
}
为了获得 100% 的代码覆盖率,我需要进入 catch 块。但我绝对不知道如何才能做到这一点。在这种情况下有一些模拟框架可以帮助我吗?如果是这样 - 怎么办?或者还有另一种方法而不必捕获异常吗?
I got the following method:
private MessageDigest getMessageDigest() {
try {
return MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException e) {
throw new Error(e);
}
}
To get 100% code coverage I need to get into the catch block. But I am absolutely not sure how I can do that. Is there some mocking framework that could help me in this case? If so - how? Or is there even another way without having to catch an exception?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
MessageDigest 上的 getInstance 方法看起来像一个静态方法。静态方法不能被模拟。我同意 Ratchet 的观点,即您不应该以 100% 的代码覆盖率为目标,而应该专注于测试具有复杂代码的区域。
The getInstance method on MessageDigest looks like a static method. Static methods cannot be mocked. I agree with ratchet that you should not aim for 100 % code coverage but focus on testing the areas with complex code instead.
我将其写为:
并声明因为 catch 块无法访问,所以不需要对其进行测试。
I'd write this as:
And declare that because the catch block is unreachable, it doesn't need to be tested.
老实说,在这种情况下,您不需要覆盖该代码,它是不可访问的样板,以确保您不必担心用户代码中的检查异常(大多数情况下,如果您可以解释为什么 2 的原因,98% 的覆盖率就足够了)错过的百分比)
honestly in this case you don't need to cover that code it's non reachable boilerplate to ensure you don't have to worry about checked exceptions in the user code (most of the time 98% coverage is sufficient if you can explain why the 2 percent got missed)
为了跟进这个问题,可以使用 PowerMock 来完成。
作为摘录,这是我的工作代码:
“MyClass”类将简单地执行类似以下操作:
在附加测试中,您可以编写
而不是我提到的 return 来到达您的 catch 块。
但请注意,使用 PowerMock 有一些缺点。它通常会使用更多的内存和更多的启动时间,因此您的测试将运行更长时间。对于这个特定的测试来说,这不会产生太大的影响,但只是需要注意一下。
Just to have a follow-up on this question, it can be done with PowerMock.
As an extract, this is my working code:
The class "MyClass" will simply do something like:
In an additional test, you could write
instead of my mentioned return, to get to your catch block.
Do note, however, that using PowerMock has some drawbacks. It will generally use more memory and more instatiation time, so your test will run longer. For this specific test, it won't make a big difference, but just as a head's up.
您的异常是无法访问的,因为该异常永远不会被抛出。我认为像 Mockito 这样的东西做类似的事情是合乎逻辑的:
但它仍然没有多大意义。您最好像这样编写代码:
否则您需要修改您的方法以使其可测试:
Your exception is unreachable because that exception will never be thrown. I suppose it's logical with something like Mockito to do something akin to:
But it still doesn't make much sense. You are better off writing your code like:
otherwise you'll need to modify your method to be testable:
就我而言,我们的管道需要 100% 的覆盖率,因此我执行了以下操作:
MessageDigest
的实例catch
子句,抛出一个AssertionError("unreachable", e)
来表明肯定不可能到达这里jacoco.gradle 用于 jacocoTestReport 和 jacocoTestCoverageVerification 任务。要了解如何排除内部类,请查看我的其他帖子: 使用 Gradle 时如何忽略 Jacoco 中的内部静态类
(它链接到另一篇关于如何在 Maven 中执行此操作的文章,以防您使用它)
我将该方法提取到一个类中,因为 Gradle 没有一致的语法来忽略类中的成员。检查 Jacoco 的过滤选项 和 此处
In my case, our pipeline needs 100% coverage, so I did the following:
MessageDigest
catch
clause, throw anAssertionError("unreachable", e)
to indicate that it is definitely impossible to reach herejacoco.gradle
forjacocoTestReport
andjacocoTestCoverageVerification
tasks. To know how to exclude inner class, check my other post: How to ignore inner static classes in Jacoco when using Gradle(which links to another post of how to do it in Maven, in case you use it)
I extract the method to a class, because Gradle does not have a consistent syntax to ignore members in a class. Check Filtering options of Jacoco and here
您可以创建一个包装器 MessageDigest 类:
You can create a wrapper MessageDigest class:
我遇到了类似的东西,发现这篇文章对于模拟 MessageDigest.getInstance() 非常有用。
https://www.baeldung.com/mockito-mock-static-methods
I came across something similar and found this article very useful for mocking MessageDigest.getInstance().
https://www.baeldung.com/mockito-mock-static-methods