java - 是否正在创建一个私有(private)构造函数来测试不良做法?

标签 java unit-testing constructor

我遇到过一些 java 代码,其中公共(public)构造函数使用一堆 new 运算符调用包私有(private)构造函数来创建新对象。

public class Thing {

    //public
    public Thing(String param1, int paramm2) {
        this(param1, param2, new Dependency1(), new Dependency2());
    }

    //package-private for the sake of testing
    Thing(String param1, int param2, Dependency1 param3, Dependency2 param4) {
        this.memberVar1 = param1;
        this.memberVar2 = param2;
        this.memberVar3 = param3;
        this.memberVar4 = param4;
    }


    //...rest of class...
}

在我看来,这是错误的,因为您正在编写代码来测试它,而不是编写正确的代码。我想其他两个选项(我能想到的)是创建工厂或使用 PowerMockito 在适用的情况下注入(inject)新对象。就个人而言,我会写成如下所示。

public class Thing {

    //public
    public Thing(String param1, int paramm2) {
        this.memberVar1 = param1;
        this.memberVar2 = param2;
        this.memberVar3 = new Dependency1();
        this.memberVar4 = new Dependency2();
    }

    //...rest of class...
}

实现它的最佳实践/正确方法是什么?

最佳答案

在发布的任何内容中包含特定于测试的代码通常是一种不好的形式(但也有异常(exception),所以不要仔细阅读)。这里有几个原因。

<强>1。外部人员可能会以您意想不到的方式使用测试构造函数,将所有内容都处理掉,因为他们要么没有阅读说明它用于测试的文档,要么开发人员忘记记录它。

假设您想为 Thing 编写一些有用的扩展,但您无法在 Thing 的公共(public)/ protected API 中找到任何符合您要求的内容.然后你会发现这个包私有(private)的构造函数似乎允许你所希望的,只是后来发现它破坏了你的代码。您仍然无法做您想做的事情,并且您浪费了时间探索未成功的 API 部分。这样做的任何人都会对该 API 留下负面评价,并且不太可能将其推荐给其他人。

<强>2。重构包名称会破坏内容。

由于 Java 的默认可见性工作方式,此测试代码对生产代码中发生的重构不是很有弹性。如果测试代码驻留在同一个包中,则它只能调用该构造函数。如果包被重命名,调用它的测试代码将无法访问它,从而导致编译错误。当然,对于开发代码和测试的人来说,这是一个简单的修复,但即使不添加这个小烦恼,重构也已经不再有趣了。如果一群人以前能够成功地使用包私有(private)的东西来满足他们的需求,这将成为一个主要问题 - 现在他们的所有代码也被破坏了。

在某些情况下,很难编写可在测试和生产环境中运行的代码(例如,仅在您的应用程序联网时运行的函数)。在这些情况下,依赖注入(inject)可能是你的 friend ,但如果可以避免更复杂的测试方案而不牺牲功能覆盖率或在你的 API 中添加你不希望其他开发人员看到的 Hook ,那么简单的测试总是最好的。

关于java - 是否正在创建一个私有(private)构造函数来测试不良做法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40473191/

相关文章:

java - 如何在 Kotlin 中获取 Java 原语 void 类?

java - 我有一个用 C/C++ 编写的应用程序,每次系统启动/重新启动时都需要运行。实现这一目标的最简单方法是什么?

java - 无法创建构造函数

c++ - 从 QTest 模拟点击的 QML 元素

c# - 如何对 Request.Form [""] 进行单元测试?

java - 构造函数未定义

c# - 为什么我们需要静态私有(private)数组来初始化其他非静态私有(private)数组字段?

java - 行程解压

Java序列化在任何语言之间传输数据

javascript - 编写 "unit testable"jQuery 代码?