💻
標準入力/標準出力をテストする
何をしたいか
極稀に、標準入力で何が入力されたか・標準出力で何が出力されたかをテストしたいことがあります。
やり方を備忘録としてメモしておきます。
環境
- JDK 21
- JUnit 5.12.2
多少バージョンが違っていても大丈夫だと思います。たぶん。
テスト対象
Sample1.java
public class Sample1 {
public List<Integer> input() {
Scanner scanner = new Scanner(System.in);
System.out.print("整数を指定してください(複数の場合は半角スペース区切り、最後は半角スペース+a) -> ");
ArrayList<Integer> idList = new ArrayList<>();
for (int id; scanner.hasNextInt(); ) {
id = scanner.nextInt();
idList.add(id);
}
return idList;
}
}
Sample2.java
public class Sample2 {
public void output(String message) {
System.out.println(message);
}
}
標準入力のテスト
Javaの標準入力 System.in は java.io.InputStream 型です。
テスト時は、これを java.io.ByteArrayInputStream ( java.io.InputStream のサブクラス)に差し替えます。
System.in は staticフィールドなので、差し替えたままだと他の箇所にも影響が出てしまいます。テスト終了後は元の InputStream に戻します。
Sample1Test.java
public class Sample1Test {
Sample1 sample1 = new Sample1();
// 標準入力を元に戻すために保存しておく
InputStream originalIn = System.in;
@AfterEach
void afterEach() {
// テスト後、標準入力を元に戻す
System.setIn(originalIn);
}
@Nested
@DisplayName("input()")
class Input {
@Test
@DisplayName("標準入力から「1 2 3」が入力されると、リスト[1, 2, 3]を取得できる")
void success() {
// 差し替え
ByteArrayInputStream bais = new ByteArrayInputStream("1 2 3".getBytes(StandardCharsets.UTF_8));
System.setIn(bais);
// 実行
List<Integer> actual = sample1.input();
// 検証
assertEquals(List.of(1, 2, 3), actual);
}
}
}
標準出力
Javaの標準出力 System.out は java.io.PrintStream 型です。
PrintStream のコンストラクタは java.io.OutputStream ・ boolean ・ java.nio.charset.Charset を引数で受け取ります。
テスト時は、コンストラクタに java.io.ByteArrayOutputStream ( OutputStream のサブクラス)を指定した PrintStream に差し替えます。
System.out は staticフィールドなので、差し替えたままだと他の箇所にも影響が出てしまいます。テスト終了後は元の PrintStream に戻します。
Sample2Test.java
public class Sample2Test {
Sample2 sample2 = new Sample2();
// 標準出力を元に戻すために保存しておく
PrintStream originalOut = System.out;
@AfterEach
void afterEach() {
// テスト後、標準出力を元に戻す
System.setOut(originalOut);
}
@Nested
@DisplayName("output()")
class Output {
@Test
@DisplayName("指定した文字列が、改行付きで標準出力に出力される")
void success() {
// 差し替え
ByteArrayOutputStream baos = new ByteArrayOutputStream();
PrintStream ps = new PrintStream(baos, true, StandardCharsets.UTF_8);
System.setOut(ps);
// 実行
sample2.output("Hello!");
// 検証
assertEquals("Hello!" + System.lineSeparator(), baos.toString(StandardCharsets.UTF_8));
}
}
}
Discussion