【问题标题】:Disable a part of Java Program during JUnit testing在 JUnit 测试期间禁用部分 Java 程序
【发布时间】:2018-11-21 09:21:46
【问题描述】:

我正在使用 JUnit 测试我的 Java 程序。 该程序包括一些 JavaFX GUI 界面和其他日志记录代码。但是,在测试期间,我不希望对这些进行测试。有没有办法在测试和开发之间切换代码?

描述可以很抽象,我举个例子:

public class Helloworld {

    /**
     * @param args the command line arguments
     */
    public static int greetingCnt = 0;

    public static void main(String[] args) {
        Helloworld helloword = new Helloworld();
        helloword.greetWorld();
        helloword.greetWorld();
        helloword.greetWorld();
        System.out.println("Greating count: " + greetingCnt);
    }

    public void greetWorld() {
        System.out.println("Hello World!");
        ++greetingCnt;
        //some other computation...
    }

}

在这个例子中,如果我只想测试 greetingCnt 的正确数量但不想打印任何东西或执行任何额外的计算。但在实际程序执行过程中,对程序的功能没有影响。请问有什么办法可以吗?

谢谢!

【问题讨论】:

  • 问题似乎在于代码的结构方式,即打印和增量在同一个地方完成。我不确定如何在此示例中解决此问题(可能在其他地方增加并测试 that 功能?)但也许可以在您的实际情况下完成。
  • 嗨 Federico,感谢 cmets。我在想的是Java中是否有任何相当于#define或预处理器的东西,以便程序能够根据不同的场景稍微改变行为。
  • abstraction 是编写可测试代码的关键 - 将您的关注点分开,然后编写实际的 unit 测试。 SOLID 是你的朋友。

标签: java unit-testing testing junit


【解决方案1】:

没有你的额外努力是不可能的。

计算机根本无法判断哪个计算会影响什么。

您可以通过替换默认的PrintWriter 来关闭打印到控制台等特定功能,但没有通用的解决方案。

【讨论】:

  • 您好,非常感谢您的回答。 helloworld 程序当然只是一个例子。我在想是否有任何类似整个程序的通用开关,这样我就可以在测试模式和正常开发模式之间切换。
  • @EugeneH 你可以从日志框架的工作中获得灵感。您设置一个日志记录级别,当您调用日志记录方法时,您指定它应该和不应该记录的级别。我非常怀疑用ifs 喷洒你的代码是一种优雅且可维护的解决方案
  • @EugeneH 不,没有这样的开关,因为理论上不可能实现它。
【解决方案2】:

针对您的具体情况:您可以使用PowerMock in order to mock System.out,但老实说,我忽略了它可能产生的全部副作用。


更一般地说:您要查找的内容称为Mock object,基本上允许Object 的实例不做任何事情,这只是运行代码的最低要求。

对于您的情况,模拟 System.out 将允许您运行对 System.out.println() 的调用,而无需实际调用它们。 因此,您的代码会像这样执行:

public class Helloworld {

/**
 * @param args the command line arguments
 */
public static int greetingCnt = 0;

public static void main(String[] args) {
    Helloworld helloword = new Helloworld();
    helloword.greetWorld();
    helloword.greetWorld();
    helloword.greetWorld();
    // System.out.println("Greating count: " + greetingCnt);
}

public void greetWorld() {
    // System.out.println("Hello World!");
    ++greetingCnt;
    //some other computation...
}

我可以进一步解释它真正是如何发生的,但我想这足以回答你的问题。如果您好奇,可以查看测试的运行时执行情况,以检查模拟对象的真实类型。

【讨论】:

    【解决方案3】:

    您首先需要使您的 Java 程序可配置。

    一种方法是使用 Java property files。然后,您可以使用特定属性来禁用程序的某些部分。

    然后您可以在测试期间使用一个属性文件,并在正常执行期间使用另一个。

    属性文件通常是 Java 类路径上的资源。然后,您可以使用包含描述测试配置的属性文件的类路径运行测试。

    【讨论】:

    • 嗨@avandeursen 非常感谢您的回答。所以据我了解,属性文件就像加载配置一样,但是,在获取配置后,如何实现测试和开发代码的分离?我应该使用 if 语句还是 switch/case 语句?还是有另一种更系统的方法?非常感谢您的帮助:)
    猜你喜欢
    • 2015-05-27
    • 1970-01-01
    • 1970-01-01
    • 2018-04-05
    • 2016-04-17
    • 2013-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多