junit - 使用assertTrue而不是assertNull时丢失分支

标签 junit code-coverage bytecode emma jacoco

在 Java/Junit 中,我需要使用某个对象测试 null。我可以通过多种方法来测试条件,但我在大多数测试中都使用assertTrue。当我检查assertTrue 中的空值时,EclEmma 指出它仅测试一个分支。

当我手动将语句解析为变量时(例如将结果设置为 bool 值并将其传递给assertTrue),代码覆盖率在断言上被视为完整,但在变量初始化行上则不完整。

为什么会发生这种情况?这是否与 Java 显然添加的额外字节代码有关,如 http://sourceforge.net/apps/trac/eclemma/wiki/FilteringOptions 中提到的?任何解决方案(除了使用其他断言语句)。

断言正确:

assertTrue( myObject == null ); //1 of 2 branches

断言正确:

boolean test = (myObject == null); //1 of 2 branches missing
assertTrue(test); // complete

断言空:

assertNull( myObject ) //complete;

最佳答案

对于大多数 bool 表达式,Java 编译器会在字节码中生成额外的分支。 JaCoCo 基于生成的字节代码(而不是基于原始 Java 代码)生成“分支覆盖率”,因此显示您将使用的几乎所有 bool 表达式的附加分支覆盖率信息。

在您的代码中,您使用的 bool 表达式是 myObject == null

为了计算该值,Java 编译器会生成代码,将两个参数压入堆栈,然后执行条件跳转以将 1(真)或 0(假)压入堆栈。 JaCoCo 报告此条件跳转的分支覆盖率。

因此,您使用 myObject == null 的事实会触发您所描述的行为。

作为其他一些示例,请尝试以下操作:

boolean t = true;
boolean f = false;
boolean result1 = (t && f) || f; // 3 out of 6 missed.
boolean result2 = !t;            // 1 out of 2 missed.

例如,如果 bool 表达式由函数返回,并在其他地方的 if-then-else 语句中用作条件,则这可能很有用。虽然主要是 Java 编译器工作方式的结果,但它有助于评估原始 Java 代码的条件覆盖率(而不仅仅是分支覆盖率)。

此功能没有详细记录,但这里有一些提示:

因此,它确实与生成的额外字节代码有关,但与过滤选项所针对的合成字节编译器结构的具体示例无关。

注意:由于最初的答案过于猜测,因此进行了重大编辑。感谢@ira-baxter 的精彩和批判性讨论。

关于junit - 使用assertTrue而不是assertNull时丢失分支,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10146032/

相关文章:

javascript - Protractor:Jasmine-Reporter (jasmine2) 正在生成奇怪的 Junit XML 报告

java - 非常简单的一步一步的 JBehave 设置教程?

java - 使用 Byte Buddy 的简单前后方法拦截器

Javassist - 如何将行号添加到方法

java - ASM 字节码替换功能未完成

使用我自己的模型作为参数执行单元测试时出现 java.lang.AssertionError

java - 在 Java 生产代码中使用 Junit Assert API 可以吗

c# - DotCover 不覆盖引用的 DLL

java - 仅在新代码上测量代码覆盖率

code-coverage - 提交消息和覆盖范围显示在 Gitlab CI 构建 (Gitlab 8.6.5) 中