通过 junit 测试主要方法

2022-09-01 10:48:18

我写了一个类,它从控制台和main方法中的参数中获取输入。main 方法为不同的控制台输入调用不同的方法,并为不同的参数调用不同的函数。因此,我想通过模仿文件中的这些输入来测试Junit的这个主要方法。我该怎么做?junit中是否有任何特殊规定来测试该类的主要方法?


答案 1

要从文件中提供输入,请创建 a 并将其设置为流。您可能希望在main方法完成后将原始方法设置回去,以确保以后使用它的任何内容仍然有效(其他测试,JUnit本身...)FileInputStreamSystem.in

下面是一个示例:

@Test
public void testMain() throws IOException {
    System.out.println("main");
    String[] args = null;
    final InputStream original = System.in;
    final FileInputStream fips = new FileInputStream(new File("[path_to_file]"));
    System.setIn(fips);
    Main.main(args);
    System.setIn(original);
}

在你的实际代码中,你会想要处理任何IOExceptions,并使用比文件的完整路径更好的东西(通过类加载器获取它),但这给了你一般的想法。


编辑:

几年后,再多一些智慧,我不得不同意迈克尔·劳埃德·李(Michael Lloyd Lee mlk)的答案,认为这是更好的方法,如果可能的话,应该更喜欢什么。在包含方法(甚至是单独的类)的类中,应该有一个接受任意数组和参数数组的方法。它可以是一个静态方法。然后,该方法只需将流作为参数来调用它。mainInputStreammainSystem.in

public class Main {
    public static void main(String[] args) {
        start(System.in, args);
    }
    public static void start(InputStream input, String[] args) {
        // use input and args
    }
}

或者,您可以有一个类,其构造函数接受参数数组以创建正确配置的实例,然后在其上调用一个接受 的实例方法,如下所示:InputStream

public class Main {
    public static void main(String[] args) {
        Bootstrapper bootstrapper = new Bootstrapper(args);
        bootstrapper.start(System.in);
    }
}

public class Bootstrapper { // just some name, could be anything else

    // could have some instance fields here...
    
    public Bootstrapper(String[] args) {
        // use the args to configure this instance, set fields, get resources...
    }
    
    public void start(InputStream input) {
        // use input
    }
}

任何最符合要求和程序设计的内容。在这两种情况下,您最终都会得到一些可以使用从文件中获取的内容进行单元测试。对 执行简单的静态方法调用的测试,或创建 Bootstrapper 实例然后调用其方法的测试。现在,您的测试不再依赖于流。main方法所做的工作最少,并且足够简单,您可以信任其正确性而无需单独测试。在某些时候,一段代码变得如此微不足道,以至于测试它相当于不信任编译器。这些主要方法中的问题很快就会变得明显,因为它是您知道的一种方法,将始终被调用。执行太多或复杂的主要方法通常表明代码中缺乏模块化。InputStreamMain.startstartSystem.in

我保留了原始答案,因为它确实提供了一个解决方案,以防您真的无法摆脱主要方法的使用和测试。这就是为什么我首先写它的原因,因为我无法确定提问者的约束。有时有人只是想直接回答他们的确切问题,因为没有更好的方法;你不允许更改代码,或者重构它太费劲,没有预算,或者使用了一些硬编码的库来使用系统流等。请注意,无论如何,原始答案都不太可靠。如果测试是并行运行的,而不是按顺序运行的,则换出系统流可能会导致意外和不一致的故障。System.in


答案 2

IMO测试主要方法的最佳方法是让主要方法绝对不做任何事情,只需设置世界并启动它。通过这种方式,一个简单的集成测试给出了“世界是否已建立”的答案。

然后,所有其他问题都变得更容易回答。

main 方法为不同的控制台输入调用不同的方法,并为不同的参数调用不同的函数。

它不应该,它应该调用。此服务像任何其他服务一样经过测试。someService.somemethod(args)

因此,我想通过模仿文件中的这些输入来测试Junit的这个主要方法。我该怎么做?

注入某种形式的假货或使用临时文件夹 JUnit 规则。


推荐