【发布时间】:2021-12-18 07:05:37
【问题描述】:
我必须测试一个程序,用户必须输入 3 个数字,然后他会在控制台输出中得到结果。
我编写了测试并重定向了 System.in 和 System.out。 我的测试用例如下所示:
private static ByteArrayOutputStream mockOut;
@Test
public void correct_input_test() {
test("> x = 0, y = 0", 1, 0, 0);
test("> x = -1, y = 0", 1, 0, -1);
}
这是预期的控制台输出作为第一个参数和 3 个 int 参数来准备输入流。
test()方法如下:
private static void test(String expected, int ... args) {
set(args); // preparing inputstream and redirecting Sys.i/o
run(expected); // running program test after setting up
}
根据需要允许尽可能多的整数输入。这些参数进一步传递给 set() 方法,我在该方法中创建输入流并重定向 System.in set() 方法:
private static void set(int... args) {
String s = Arrays.stream(args)
.mapToObj(String::valueOf)
.collect(Collectors.joining(" ")); // assembling args String
System.setIn(new ByteArrayInputStream(s.getBytes())); // redirecting Sys.in
mockOut = new ByteArrayOutputStream();
PrintStream stream = new PrintStream(mockOut);
System.setOut(stream); // redirecting Sys.out
}
传递的参数 1、0、0 变成了 String s = "1 0 0"
最后在设置之后我运行调用我的程序的方法
private static void run(String expected) {
Main.main(null); // call program to catch result
String[] consoleLines = mockOut.toString().split("\n"); // split console output
assertEquals(expected, consoleLines[consoleLines.length-1]); // compare lines
}
在这里,我在 mockOut 对象中获得的单独的控制台输出行拆分,并将最后一行与预期的字符串进行比较。
只有在我测试一个测试用例时才有效(如果我注释掉这些测试用例中的任何一个)。
@Test
public void correct_input_test() {
// test("> x = 0, y = 0", 1, 0, 0);
test("> x = -1, y = 0", 1, 0, -1);
}
但是,如果我在第二次尝试调用程序之后尝试运行两者,它会得到一个带有 java.util.NoSuchElementException 的空输入流,我实际上不知道为什么。 我试图关闭流,但我想这没关系。每次我调用 set() 时,我都会使用非空的 args-string 创建新的 InputStream。 我还尝试恢复默认 System.in 并在 set() 中再次重定向它 - 没有效果。
谁能解释一下我到底忘记了什么?
UPD。我将我的代码与方法分开来解释哪个是哪个,但以防它会增加可读性 - 下面是完全相同的代码:
private static ByteArrayOutputStream mockOut;
@Test
public void correct_input_test() {
test("> x = 0, y = 0", 1, 0, 0);
test("> x = -1, y = 0", 1, 0, -1);
}
private static void test(String expected, int ... args) {
set(args); // preparing inputstream and redirecting Sys.i/o
run(expected); // running program test after setting up
}
private static void set(int... args) {
String s = Arrays.stream(args)
.mapToObj(String::valueOf)
.collect(Collectors.joining(" ")); // assembling args String
System.setIn(new ByteArrayInputStream(s.getBytes())); // redirecting Sys.in
mockOut = new ByteArrayOutputStream();
PrintStream stream = new PrintStream(mockOut);
System.setOut(stream); // redirecting Sys.out
}
private static void run(String expected) {
Main.main(null); // call program to catch result
String[] consoleLines = mockOut.toString().split("\n"); // split console output
assertEquals(expected, consoleLines[consoleLines.length-1]); // compare lines
}
UPD。 这是堆栈跟踪:
java.util.NoSuchElementException:
Arguments input incomplete.
at Main.in(Main.java:169)
at Main.main(Main.java:19)
at MainTest$MainMethodTest.run(MainTest.java:75)
at MainTest$MainMethodTest.test(MainTest.java:71)
at MainTest$MainMethodTest$SwapMethodTest.correct_input_test(MainTest.java:29)
我知道异常的确切来源。 这是从 main() 调用以获取用户输入的 in() 方法,当 Scanner 尝试读取 next() 时捕获的异常输入流:
public static int in(String message, int from, int to) {
if (message != null && !message.isEmpty()) {
System.out.print(message);
}
try {
String input = scanner.next();
int num;
/* this code works correctly for me
and is just to check
if user typed correct number
and if the number is in range.
try {
if ((num = Integer.parseInt(input)) < from) {
throw new IllegalArgumentException("\n\nExpected: value >= " + from + "\nActual: value = " + num + "\n");
} else if (num > to) {
throw new IllegalArgumentException("\n\nExpected: value <= " + to + "\nActual: value = " + num + "\n");
} else {
return num;
}
} catch (NumberFormatException e) {
throw new NumberFormatException("\n\nExpected: integer number\nActual: " + input + "\n");
}
*/
} catch (NoSuchElementException e) {
throw new NoSuchElementException("\n\nArguments input incomplete.");
} // at Main.in(Main.java:169) - here is line 169
}
但我不明白为什么 IS 是空的。
【问题讨论】:
-
抛出异常的堆栈跟踪是什么?
-
是的,我更新了帖子。谢谢
标签: java junit console inputstream