带有虚假用户输入的Java测试扫描仪

时间:2018-10-24 07:48:22

标签: java unit-testing junit mockito console-application

我有一个static方法,该方法使用static final Scanner从控制台获取用户输入。

测试时,我想用不同的输入(显然)创建许多测试。只要单独运行测试,此方法就可以正常工作。运行整个类是行不通的,因为(显然)扫描器已使用上一个测试的输入进行了初始化,该输入的行比第一个测试所需的行多。

我遇到的具体错误是:

java.util.NoSuchElementException: No line found

这里有一些代码需要澄清:

public class UserInputHandler {
    public static final Scanner SCANNER = new Scanner(System.in);
}

我要测试的班级(和其他一些班级)正在使用Scanner以上的语言来查询用户。

我的测试:

InputStream in = new ByteArrayInputStream("test".getBytes());
System.setIn(in);
TestClass testclass = new TestClass();
testClass.method(); // Scanner is used in this method

如何使我的测试适用于多个TestClass实例?

1 个答案:

答案 0 :(得分:4)

真正的问题在这里:

public class UserInputHandler {
    public static final Scanner SCANNER = new Scanner(System.in);
}

您正在强制该输入来自System.in。为什么不使用

public class UserInputHandler {
    public Scanner getScanner() {
      return new Scanner(someInputStream);

当然,现在您必须担心someInputStream的来源,但是:您使自己变得更加灵活。

您的代码实际上并不是在单个静态对象上,而是会进行调用并接收从 somewhere 读取的内容。然后,在测试中,您只需定义输入流,并确保可以使用这些输入流(例如,通过使UserInputHandler类的字段在实例化该类时被设置)。

换句话说:真正的解决方案是更改您的生产代码,以使其A)更加灵活并且B)易于测试。您倒退了:您编写了僵硬且难以测试的代码,现在尝试将测试用例调整为合理。

错误的方法:当您不能编写简单直接的测试时,则需要重新编写生产代码。总是。