使用Junit测试多线程Java应用程序时模拟用户控制台输入时的有趣行为

时间:2019-03-28 13:23:34

标签: java multithreading junit jvm system.in

我正在尝试使用Java中的JUnit开发自动分配评分脚本。我通过将System.in更改为包含以字节为单位的字符串数据的ByteArrayInputStream传入测试用例输入(从类路径中的文件读取)来模拟用户输入。我希望能够运行多个测试用例来检查所有用例,然后使用Gradle构建的报告来标记作业提交。

当前,我已经能够使用此链接JUnit: How to simulate System.in testing?模拟用户输入,以反映测试用例提供的输入。我还将System.out更改为PrintStream以从分配中捕获打印的语句。我的main方法产生了一个新线程,在其中完成了任务的代码,如下所示。

当我分别测试每个@Test-带注释的案例时,单元测试成功执行。但是,当我运行单个Test类中包含的所有测试时,JUnit在第一个@Test注释的情况下可以成功运行,但在最终的情况下将失败,这在这里有些意外。希望下面的代码将有助于澄清这种情况。

我的主要方法

public static void main(String ... args) {
    Assignment assignment = new Assignment();
    new Thread(assignment).start();
}

我的测试类具有一些@before和@after注释方法:

@Before
public void setup() {
    systemIn = System.in; // global variable
    systemOut = System.out; // global variable
    output = new ByteArrayOutputStream(); // global variable
    System.setOut(new PrintStream(output));
    assignment = new Assignment();
}
@After
public void conclude() {
    System.setIn(systemIn);
    System.setOut(systemOut);
}

我正在为每个测试用例的输入和输出读取相应的文件,并在下面的功能中设置测试用例的输入。

private void setInput(String data) {
    ByteArrayInputStream input = new ByteArrayInputStream(data.getBytes());
    System.setIn(input);
}

我正在如下运行每个测试用例:

@org.junit.Test // 2,3,4 ....for other cases
public void runTestCase1() { 
    testCases(1);
}

分配所使用的 IO 类如下:

public static String readLine() { // w/o try/catch blocks
    String read = reader.readLine(); // reader -> bufferedReader(new InputStream(System.in))
    return read.trim();
}

还请注意,在调用main方法之前,我正在使用Thread.sleep(50),以便成功地读取输入测试用例并将其装入System.in中,以便及时执行Assignment。

同时运行所有测试时,第一个测试给出正确的输出,即预期输出与实际输出匹配。但是,从第二种情况开始,IO.readline()会生成空指针异常,因此该赋值不会产生任何输出。经过调查,我发现在第二种情况下,System.in不再指向ByteArrayInputStream,而是指向(旧的?)BufferedInputStream。我很困惑为什么会发生这种情况(可能是由于新的线程产生了?)以及如何克服这个问题?

0 个答案:

没有答案