我正在使用 EclEmma 进行覆盖率分析。
我的 Java 代码包含一个 synchronized(MyClass.class) {} 块。
EclEmma 说它只被部分覆盖,尽管我有一个单元测试,其中一个线程可以访问而另一个线程被阻塞。
是否有可能使用 EclEmma 全面覆盖同步?
我可以以某种方式对代码进行注释以告诉 EclEmma 全面覆盖这一行吗?
亲切的问候罗杰
我正在使用 EclEmma 进行覆盖率分析。
我的 Java 代码包含一个 synchronized(MyClass.class) {} 块。
EclEmma 说它只被部分覆盖,尽管我有一个单元测试,其中一个线程可以访问而另一个线程被阻塞。
是否有可能使用 EclEmma 全面覆盖同步?
我可以以某种方式对代码进行注释以告诉 EclEmma 全面覆盖这一行吗?
亲切的问候罗杰
我不确定是否有可能获得全面报道,因为issue 2939804报告:
EMMA 始终标记
synchronized(..)
为部分覆盖例子:
synchronized (lock) // partially covered (yellow line in EclEmma)
{
// ...
}
synchronized (this) // partially covered (yellow line in EclEmma)
{
// ...
}
也许不同的工具(如 Cobertura)会产生不同的结果?(我最近没有测试过)。
2012 年 12 月更新(2 年多后):
synchronized
如果同步块包含在对象监视器上等待的代码,并且测试中断等待线程,则将亮为绿色。经过一点实验,如果块正常完成并由于异常而突然完成,我能够实现对
synchronized
线路的完全覆盖。synchronized
EclEmma 在下面使用 Jacoco 进行覆盖率分析。
正如 Jacoco 的(当前不存在的)JAVAC.SYNC 过滤选项中所解释的,该行为是为同步块生成的字节码的结果:
Java 同步块被编译成两条字节码指令:MONITORENTER 位于块的开头, MONITOREXIT 位于块的末尾。
为了确保在任何情况下都释放监视器,安装了指向另一个 MONITOREXIT 指令的异常处理程序。此异常处理程序块通常会导致部分行覆盖,从源代码的角度来看这是没有意义的。
一个相关的Jacoco 问题 245解释了如何触发异常以达到完全覆盖,如果这是需要的,@nathan-ryan 也解释了这一点:
我相信问题是MyClass.class
显然是使用
http://emma.sourceforge.net/faq.html#q.fractional.examples
由于隐藏的 Class.forName() 导致的隐式分支。这种情况很不幸,因为它很常见,但程序员几乎无法控制它。
因为 Class.forName() 可以抛出已检查的异常,所以编译器会发出一个 catch 块,将它们重新抛出为未检查的。这个 catch 块在实践中几乎不会执行,但它成功地将行标记为部分覆盖。
我在第一次通读时错过了这一点。
我将尝试重新编写我的代码以获得全面覆盖。
/罗杰