【问题标题】:JUnit test for console input and output控制台输入和输出的 JUnit 测试
【发布时间】:2012-09-08 14:40:05
【问题描述】:

我只有一种方法 main。如何检查 System.out.println() 并替换 Scanner 以使用 JUnit 自动输入值?

附:请提供一些解决方案...

public static void main(String[] args) {
    Scanner scanner = new Scanner(System.in);
    int[] arr = new int[4];

    for (int i = 0; i < arr.length; i++) {
        arr[i] = scanner.nextInt();
    }

    for (int i = 0; i < arr.length; i++) {
        int res = 0;
        int k = 0;
        int num = arr[i];
        /*.....*/
        System.out.println(num);
    }
}

【问题讨论】:

  • 我想学习如何使用它

标签: java junit io console user-input


【解决方案1】:

理想情况下,提取笨拙的依赖项,这样您就可以在没有它们的情况下进行测试。将main 改为:

public static void main(String[] args) {
  doWork(new Scanner(System.in), System.out);
}

// TODO: Rename to something meaningful
public static void doWork(Scanner input, PrintStream output) {
  // Remainder of code
}

(考虑使用Writer 而不是PrintStream 来代替output。)

那么您实际上并不需要对main 进行单元测试 - 但您可以使用基于ScannerScanner 测试StringReader,并基于StringWriter 的输出,提供您想要的任何输入并检查输出。

【讨论】:

  • 我如何使用它来拥有例如对应于多个信息提示的多个输入?
  • 我也有同样的问题。如果您发现了什么,请告诉我...!
  • @Aman:抱歉,我之前一定没看过这条评论。您将提供一个Scanner,它基本上返回您希望用户输入的所有值。
  • 谢谢。但是我使用了系统规则库stefanbirkner.github.io/system-rules
【解决方案2】:

我遇到了类似的问题,这就是我最终要做的。

首先,我建议按照@Jon-Skeet 的建议做,而不是使用类的main(String[]) 方法,而是创建一个单独的方法。

然后,您可以让该方法接受InputStream 作为参数,然后在使用传递的InputStream 作为其源的方法中创建Scanner 对象。这样,您可以在调用该方法时将任何InputStream(例如System.in)传递给该方法(下文详述)。

package my.package;

import ...;

public class MyClass
{
    public static void myMethod(InputStream inputStream)
    {
        Scanner inputScanner = new Scanner(inputStream);

        // Do stuff with the Scanner such as...
        String input = inputScanner.nextLine();
    
        System.out.println("You inputted " + input);
    }
}

现在,在您的生产源代码中,您可以调用 myMethod 并将 System.in 作为参数传递给 myMethod(System.in);

然后在您的单元测试中,您可以通过ByteArrayInputStream 创建模拟输入值:

package my.package;

import ...;

public class MyClassTest
{
    @Test
    void testMyMethod()
    {
        // Simulates a user inputting the string "Mock input" and hitting enter
        assertDoesNotThrow(myMethod(new ByteArrayInputStream("Mock input\n".getBytes())));
    }
}

瞧,您现在有了一种方法来传递您的方法模拟输入,并且整体上更加模块化。

我只想指出,但不要过多介绍,当使用 System.in 时,需要小心关闭它,在处理输入流时在单元测试中,需要小心重用引用相同的InputStream,因为它的状态可以跨使用保持。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-08-17
    • 1970-01-01
    • 1970-01-01
    • 2021-12-25
    • 1970-01-01
    • 2019-07-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多