对于依赖于 Java 中的东西的未覆盖代码,SonarQube 新代码覆盖率的质量门失败 [英] SonarQube quality gate on new code coverage fails for uncovered code that relies on things baked into Java

查看:47
本文介绍了对于依赖于 Java 中的东西的未覆盖代码,SonarQube 新代码覆盖率的质量门失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们团队中有人更改了此代码:

Someone on our team changed this code:

public class Rectangle implements Cloneable, Serializable {

    @Override
    public Rectangle clone() {
        return new Rectangle(x, y, width, height);
    }

}

到这个代码:

public class Rectangle implements Cloneable, Serializable {

    @Override
    public Rectangle clone() {
        try {
            // super.clone is safe to return since all of the Rectangle's fields are primitive.
            return (Rectangle) super.clone();
        } catch (CloneNotSupportedException e) {
            // should never happen since Cloneable is implemented
            return null;
        }
    }

}

他们编写了一个单元测试,涵盖了 try 代码路径.

They wrote a unit test that covers the try code path.

他们没有编写涵盖 catch 代码路径的测试.catch 代码路径依赖于烘焙"到 Java 中的东西,使其崩溃的唯一方法是通过删除 Cloneable 来更改类的结构 标记界面.但是如果该类结构发生变化,那么其他单元测试就会失败.

They did not write a test that covers the catch code path. The catch code path relies on things "baked" into Java, the only way to make it crash is to change the structure of the class, by dropping the Cloneable marker interface. But if that class structure changes, then the other unit test should fail.

因为 catch 代码路径没有被单元测试覆盖,所以 SonarQube 质量门新代码的代码覆盖率"失败,并且因为质量门失败,构建它的 Jenkins 作业分支失败,并且由于 Jenkins 作业失败,Bitbucket 将不允许合并.

Because the catch code path isn't covered by a unit test, the SonarQube quality gate "code coverage on new code" fails, and because the quality gate fails, the Jenkins job that builds that branch fails, and because the Jenkins job fails, Bitbucket won't allow the merge.

已经尝试过:

  • 失败:在 SonarQube 中标记为误报:代码覆盖质量门不可能,您只能针对基于规则的问题执行此操作.
  • DIRTY HACK:在运行作业之前关闭(或降低)SonarQube 中的质量门限,并在分支合并后重新打开它:这可行,但感觉太脏了,我认为它应该发生得非常异常.我正在寻找一种不需要人工干预的更好的解决方案.
  • 失败:模拟 Rectangle:不起作用,super.clone() 必须被模拟,在 Object.clone(),这是一个受保护的方法.
  • FAILED:通过增加一个类来伪造它,例如Rectangle -> EvilRectangle -> TestRectangle,其中 EvilRectangle 抛出 CloneNotSupportedException 然后TestRectangle 是为测试实例化的实际类.不会工作,因为这会改变 clone() 方法的签名,它不会在 Rectangle 中抛出 CloneNotSupportedException.
  • FAILED: Mark as false positive in SonarQube: not possible for code coverage quality gate, you can only do that for rule-based issues.
  • DIRTY HACK: Turn off (or lower) the quality gate in SonarQube before running the job, and turning it back on after the branch is merged: this works, but it feels so dirty that I think it should happen really exceptionally. I'm looking for a better solution that doesn't require a manual intervention.
  • FAILED: Mocking Rectangle: won't work, super.clone() would have to be mocked, which is on Object.clone(), which is a protected method.
  • FAILED: Fake it by having an additional class, e.g. Rectangle -> EvilRectangle -> TestRectangle, where EvilRectangle throws the CloneNotSupportedException and then TestRectangle is the actual class instantiated for the test. Won't work because that would change the signature of the clone() method, it doesn't throw CloneNotSupportedException in Rectangle.

问题

  • Java 人员:
  • 如何为 catch 代码路径编写单元测试?
  • 如何在不更改其公共 API 的情况下重写代码,使其变得可测试?
  • SonarQube 人员
  • 如何通过质量门新代码的代码覆盖率"?
  • Java people:
  • How does one write a unit test for the catch code path?
  • How can the code be rewritten, without changing it's public API, so that it becomes testable?
  • SonarQube people
  • How does one make the quality gate "code coverage on new code" pass?

编辑历史

  • 添加了原始代码

推荐答案

Apache Commons Lang 提供了一个 clone 方法,该方法进行深度复制并且不抛出异常.没有例外意味着不需要 try/catch,因此测试的代码路径减少了.我在一篇讨论 Object.clone() 替代方案的文章中发现了这一点:https://dzone.com/articles/java-cloning-copy-constructor-vs-cloning

Apache Commons Lang provides a clone method that does a deep copy and does not throw an exception. No exception means no try/catch needed, thus one less code path to test. I found this in an article discussing alternatives for Object.clone(): https://dzone.com/articles/java-cloning-copy-constructor-vs-cloning

将此添加到pom.xml:

<dependency>
  <groupId>commons-lang</groupId>
  <artifactId>commons-lang</artifactId>
  <version>2.6</version>
</dependency>

将此添加到您的类的导入语句中:

Add this to the import statements of your class:

import org.apache.commons.lang.SerializationUtils;

您的类必须具有实现可序列化.添加一个private static final long serialVersionUID,这显然是一个最佳实践.

Your class must have implements Serializable. Add a private static final long serialVersionUID, that's apparently a best practice.

然后将 super.clone() 替换为 SerializationUtils.clone(this).

最后,您可以删除 clone() 语句周围的 try/catch,或从方法中删除 trows.

And finally, you can remove the try/catch around the clone() statement, or remove the trows from the method.

这是我的新代码:

@Override
public Rectangle clone() {
    return (Rectangle) SerializationUtils.clone(this);
}

之前的单元测试已经覆盖了它,并且该单元测试仍然通过.

It was already covered by a unit test from before, and that unit test still passes.

这篇关于对于依赖于 Java 中的东西的未覆盖代码,SonarQube 新代码覆盖率的质量门失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆