我正在尝试使用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。我很困惑为什么会发生这种情况(可能是由于新的线程产生了?)以及如何克服这个问题?