当前位置: 首页 > 知识库问答 >
问题:

为什么JaCoCo没有覆盖我的字符串开关语句?

容学林
2023-03-14

我有一个switch语句,它从字符串中提取寻址模式,我编写了单元测试来涵盖我认为所有可能发生的情况,但JaCoCo似乎跳过了我的switch语句,导致覆盖率较低。

为什么,如果我的所有case语句(包括默认值)都在测试中执行,switch语句不被计算为命中?

共有1个答案

夏俊人
2023-03-14

对于按字符串切换

class Fun  {
  static int fun(String s) {
    switch (s) {
      case "I":
        return 1;
      case "A":
        return 2;
      case "Z":
        return 3;
      case "ABS":
        return 4;
      case "IND":
        return 5;
      default:
        return 6;
    }
  }
}

Oracle Java编译器生成的字节码类似于以下代码(Eclipse compiler for Java生成的字节码略有不同)

    int c = -1;
    switch (s.hashCode()) {
      case 65: // +1 branch
        if (s.equals("I")) // +2 branches
          c = 0;
        break;
      case 73: // +1 branch
        if (s.equals("A")) // +2 branches
          c = 1;
        break;
      case 90: // +1 branch
        if (s.equals("Z")) // +2 branches
          c = 2;
        break;
      case 64594: // +1 branch
        if (s.equals("ABS")) // +2 branches
          c = 3;
        break;
      case 72639: // +1 branch
        if (s.equals("IND")) // +2 branches
          c = 4;
        break;
      default: // +1 branch
    }
    switch (c) {
      case 0: // +1 branch
        return 1;
      case 1: // +1 branch
        return 2;
      case 2: // +1 branch
        return 3;
      case 3: // +1 branch
        return 4;
      case 4: // +1 branch
        return 5;
      default: // +1 branch
        return 6;
    }

因此,包含6个大小写的原始switch-statement在字节码中由一个包含6个大写的hashcodestring的开关加上5个if-statements加上另一个包含6个大写的开关来表示。要查看这个字节码,可以使用javap-c

import org.junit.Test;
import static org.junit.Assert.*;

public class FunTest {
  @Test
  public void test() {
    // original strings:
    assertEquals(1, Fun.fun("I"));
    assertEquals(2, Fun.fun("A"));
    assertEquals(3, Fun.fun("Z"));
    assertEquals(4, Fun.fun("ABS"));
    assertEquals(5, Fun.fun("IND"));

    // same hash codes, but different strings:
    assertEquals(6, Fun.fun("\0I"));
    assertEquals(6, Fun.fun("\0A"));
    assertEquals(6, Fun.fun("\0Z"));
    assertEquals(6, Fun.fun("\0ABS"));
    assertEquals(6, Fun.fun("\0IND"));

    // distinct hash code to cover default cases of switches
    assertEquals(6, Fun.fun(""));
  }
}

和JaCoCo 0.7.9生成的报告作为证明:

JaCoCo Version0.8.0提供了筛选器,包括javac为按字符串切换生成的字节码筛选器。因此,即使没有额外的测试,也会生成以下报告:

 类似资料:
  • 我使用JaCoCo进行代码覆盖。单元测试报告是用junit创建的,它们被正确地导入,因此单元测试信息被正确地显示出来。问题是,我得到了错误消息:没有关于每个测试覆盖率的信息。代码覆盖率显示单元测试、集成测试和整体覆盖率的值为0%。我检查了sonar项目中所有需要的信息,如二进制、src、测试等属性。 我使用的是:<br>-SonarQube 4.5.1<br>-SonarRunner 2.4<br

  • 我正在为我的申请写测试。我已经为我的gradle项目安装了jacoco插件。在做了测试覆盖率报告后,我看到红色的“公共类MyClass”,这意味着它没有被覆盖。 那么,我如何修复这个问题,并将其覆盖(用绿色着色)?

  • 问题内容: 好的,我从很多地方和来源都听说过,每当我覆盖equals()方法时,我也需要覆盖hashCode()方法。但是请考虑以下代码 这里的输出为true,完全按照我想要的方式为false,我根本不关心重写hashCode()方法。这意味着hashCode()覆盖是一种选择,而不是每个人都说的强制性选择。 我想要第二次确认。 问题答案: 它对您有用,因为您的代码未使用任何需要API的功能(Ha

  • 我有一个配置了jacoco插件的Gradle项目来报告测试代码覆盖率。我的单元测试是在Spock框架中编写的。 尽管Jacoco插件生成HTML报告,但它报告所有类的代码覆盖率为0%。 我在谷歌上搜索了很多,没找到我缺少的东西。有人和Gradle Jacoco合作过Spock代码吗?

  • 我正在尝试使用Sonarqube 7获得每个测试功能的覆盖范围。 我正在使用Jacoco-maven-plugin,我的测试正在使用JUnit 5运行。 我成功地在Sonarqube dashboard上获得了全局覆盖,但是我想更深入地了解哪些测试覆盖了我的类的哪些行。 我已经尝试了这里给定的配置,但是没有成功:我在日志中得到下面的消息“没有关于每个测试覆盖率的信息”。我看到这可以通过添加一个监听

  • 问题内容: 我有一个Android应用程序,我想检查安装的应用程序名称是否与传递给包含此代码的函数的字符串匹配。代码和示例如下: 假设您打过电话,并且手机上的应用程序名称与返回的名称相同。但是,它永远不会。我记录了结果,它应该匹配,但事实并非如此。任何人都可以请问我为什么这行不通吗? 问题答案: 使用String的equals()方法代替==运算符来比较字符串: 在Java中,新手遇到的最常见错误