Scanner와 System.out.println() 에 대한 테스트

꺄악 운석이다·2022년 11월 7일
1

우테코 프리코스

목록 보기
7/7

우테코 야구 숫자 게임을 구현하면서 단위 테스트 작성에 집중했다. 그러다 Scanner, System.out 가 들어간 메서드의 테스트 구현에 문제가 발생하였다.

테스트를 하려는 메서드는 다음과 같은 형식이었다.

public void isMatchedTest() {
	Scanner sc = new Scanner(System.in);
    String str = sc.nextLine();
            /*중 략*/
    System.out.println("...");
}

이 경우 일반적인 AssertJ를 사용할 수 없을 것이다. 입력인자가 입력되지 않아 리턴값 또한 배출하지 못할테니 말이다.

assertThat(isMatchedTest()).isTrue() --> 불가능

그래서 아래와 같이 해결하였다.

@Test
    @DisplayName("플레이어의_숫자가_컴퓨터의_숫자와_같을때까지_힌트를_출력하고_일치하면_끝낸다")
    void isMatchedTest() throws IOException {
        String input = "125\n132\n123";

        InputStream in = new ByteArrayInputStream(input.getBytes());
        System.setIn(in);

        OutputStream out = new ByteArrayOutputStream();
        System.setOut(new PrintStream(out));

        playGames.matchNumber(List.of(1,2,3));

        assertThat(out.toString()).contains("2스트라이크","2볼 1스트라이크", "3스트라이크");

    }

Scanner

콘솔로부터 사용자의 input를 받을 때에는 Scanner이 필요하다. 그리고 Scanner를 생성할 때는 System.in을 넣어준다. 이 덕분에 Scanner는 콘솔로부터 사용자가 입력하는 값을 받아온다.

Scanner sc = new Scanner(System.in);

이 때 System.in은 콘솔창에 사용자가 입력하는 값을 InputStream으로 담는 역할을 한다. 그러면 Scanner는 InputStream을 확인하여 사용자의 입력을 읽는다.

그러나 테스트를 할 때는 콘솔에 입력하는 대신 미리 InputStream형식의 Mock데이터를 집어넣어 Scanner가 읽어내리게 해야 한다.

String input = "123";
InputStream in = new ByteArrayInputStream(input.getBytes());
        System.setIn(in);

String input값을 ByteArrayInputStream인자로 넘겨주어 InputStream을 생성하면 콘솔에 입력하는 값을 대신할 수 있다.

System.out

System.outSystem.in의 반대로 움직인다고 생각하면 된다. System.outPrintStream으로 테스트 메서드가 채워나가야 하는 대상으로 처음부터 비어있는 상태에서 테스트를 진행하면서 PrintStream이 출력한 내용대로 채워진다.

OutputStream out = new ByteArrayOutputStream();
        System.setOut(new PrintStream(out));

먼저 ByteArrayOutputStream()을 인자로 하는 빈 PrintStream을 생성하고 System.setOut(out)으로 설정해준다. 테스트 실행시 모든 문구는 out에 바이트 형태로 저장된다.

이후 out.toString()으로 변환하여 비교하고자 하는 값과 비교하면 된다.

assertThat(out.toString()).contains("2스트라이크","2볼 1스트라이크", "3스트라이크");

테스트 결과

`

Reference :
https://stackoverflow.com/questions/31635698/junit-testing-for-user-input-using-scanner
https://stackoverflow.com/questions/1119385/junit-test-for-system-out-println/1119559#1119559
https://sakjung.tistory.com/33

profile
멸종은 면하자

0개의 댓글