要提供来自文件的输入,请创建 FileInputStream 并将其设置为 System.in 流。您可能希望在 main 方法完成后将原始设置回原处,以确保以后使用它的任何东西仍然有效(其他测试,JUnit 本身......)
这是一个例子:
@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's answer 作为更好的方法,如果可能的话应该首选什么。在包含您的 main 方法(甚至是单独的类)的类中,应该有一个接受任意 InputStream 和参数数组的方法。它可能是一个静态方法。然后main 方法只需使用System.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
}
}
以最符合要求和程序设计的为准。在这两种情况下,您最终都会得到可以使用从文件中获得的InputStream 进行单元测试的东西。对Main.start 进行简单静态方法调用的测试,或创建引导程序实例然后调用其start 方法的测试。现在您的测试不再依赖于System.in 流。 main 方法所做的工作最少,并且足够简单,您无需单独测试即可相信它的正确性。在某些时候,一段代码变得如此微不足道,以至于测试它等同于不信任编译器。这些主要方法中的一个问题很快就会变得明显,因为它是您知道将始终被调用的一种方法。 main 方法做的太多或复杂,通常说明代码缺乏模块化。
我保留原来的答案,因为它确实提供了一个解决方案,以防您真的无法通过使用 System.in 并测试主要方法。这就是我首先写它的原因,因为我无法确定提问者的限制。有时有人只想直接回答他们的确切问题,因为没有更好的方法;不允许您更改代码,或者重构它需要付出太多努力并且没有预算,或者使用了一些硬编码的库以使用系统流等。请注意,原始答案无论如何都不太健壮。如果测试是并行运行而不是顺序运行,则换出系统流可能会导致意外和不一致的故障。