在Java程序中,可以通過給System.in和System.out重新賦值來重定向標準輸入和輸出。
在單元測試的時候,為了對涉及到標準輸入和輸出的程序進行測試,常用的做法是將標準輸入和輸出重定向到文件,這樣就可以用程序?qū)崿F(xiàn)自動化的比對。但是這樣做會有文件讀取的開銷,可能會降低單元測試的運行效率。
所以,更優(yōu)的做法是將標準輸入和輸出重定向到字節(jié)流,這樣就能避免文件讀取的開銷。
為了實現(xiàn)以上的效果,可以封裝一個叫做getOutput的工具函數(shù),它以字符串的形式傳遞標準輸入內(nèi)容,并以字符串的形式返回標準輸出的內(nèi)容。
public interface Executable {
void execute();
}
/**
* 重定向程序的標準輸入,捕獲標準輸出,并以字符串的形式返回
* @param input 標準輸入
* @param executable 待驗證程序
* @return 標準輸出的內(nèi)容
*/
public static String getOutput(String input, Executable executable) {
try (
// 字節(jié)輸入流
ByteArrayInputStream is = new ByteArrayInputStream(input.getBytes(StandardCharsets.UTF_8));
// 字節(jié)輸出流
ByteArrayOutputStream os = new ByteArrayOutputStream()
) {
// 保存原始的標準輸入和輸出
InputStream in = System.in;
PrintStream out = System.out;
// 將標準輸入和輸出重定向到字節(jié)流
System.setIn(is);
System.setOut(new PrintStream(os));
// 執(zhí)行待驗證的程序
executable.execute();
// 恢復(fù)標準輸入和輸出
System.setOut(out);
System.setIn(in);
// 返回標準輸出的內(nèi)容
return os.toString();
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
可以寫以下的測試程序:
String output = getOutput("2 3 10 20 55 100", () -> {
Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
int a = scanner.nextInt();
int b = scanner.nextInt();
System.out.println(a + b);
}
});
System.out.println(output);
控制臺輸出如下:
5
30
155