Skip to content

NsTest 클래스에 메서드를 파악해보자.

her0807 edited this page Dec 7, 2021 · 4 revisions

NsTest 클래스?

ApplicationTest 테스트가 상속 받고 있는 NsTest가 뭘까? 왜 추상 클래스일까?

진행되는 전체적인 로직의 동작 원리가 궁금해졌다.

NsTest 공통 필드

PrintStream과 OutputStream 두개가 있었다. 아무래도 입출력을 관리하기 위한 필드일 듯하다.


PrintStream

이 부분에서 System.out 가 선언된 것을 보니 print, println 에 관한 작업을 할 것 같다.

  • print, println, printf와 같은 메소드들을 오버 로딩(over loading)하여 제공한다.
java.lang.Object 
  - java.io.OutputStream 
      - java.io.FilterOutputStream 
          - java.io.PrintStream

OutputStream _ ByteArrayOutputStream

데이터를 저장해두었다가, 한꺼번에 출력을 위한 저장소 개념으로 사용 되는 듯하다.


System.setOut

이 메서드는 처음 보게 되어 안에 내부를 살펴봤는데 콘솔에 관련한 동작을 제어하는 듯하다.

스크린샷 2021-12-07 오후 3 28 57

init()

클래스가 생성되면 초기화해주는 메서드로,

System.out.아래 친구들콘솔에 출력 작업이 되는 데이터 전부captor 에 저장하게끔 설정했다.

여기에 print, println 도 포함된다.

    protected final void init() {
        standardOut = System.out; 
        captor = new ByteArrayOutputStream();
        System.setOut(new PrintStream(captor));
    }

command()

실제 프로그램이 수행된 뒤, 입력 역할을 수행하기 위한 메서드이다.

입력 내용을 매개변수로 받고, 그 값을 바이트코드로 변환하고 개행으로 입력 간 사이를 나눈다.

그리고 그값을 setIn 하면 시스템 상 입력을 위한 준비가 끝난다.

    private void command(final String... args) {
        final byte[] buf = String.join("\n", args).getBytes();
        System.setIn(new ByteArrayInputStream(buf));
    }

run()

프로그램 실행 동작을 수행

    protected final void run(final String... args) {
        command(args);
        runMain();
    }

output()

System.out ~ 로 출력된 모든 데이터를 captor 에 저장해두었던 것을 toString 으로 변경하여 리턴한다.

    protected final String output() {
        return captor.toString().trim();
    }

printOutput()

output 으로 얻게 된 데이터를 출력한다.

    protected final void printOutput() {
        System.setOut(standardOut);
        System.out.println(output());
    }

NsTest 클래스가 abstract 클래스인 이유

내부를 살펴보면 runMain 만 abstract 메서드이다.

내가 유추해본 추상화 클래스 인 이유는 실제 동작 내용은 변화 가능성이 낮기 때문에 고정 시켜 두고,

main 은 변경 가능성이 높아서 NsTest 를 상속받아 사용하는 클래스에서 구현하도록 해놓기 위해서가 아닌가 싶다.


느낀점

콘솔에 출력되는 문자들을 어떻게 contains 할 수 있지? 궁금했는데

그 부분이 해소되었고, 이런 로직을 깔끔하게 라이브러리 화 한 nextstep 분들이 대단하다고 느꼈다. 

테스트 코드를 위한 클래스를 따로 생성하고, 테스트 로직을 간결하게 만든 것도 대단하고,

기능, 클래스를 분리하는게 이런거구나 알 수 있었다. 원하는 동작을 수행시킬 수 있는 능력이 부럽다.

그리고 네이밍도 기가 막히는 것 같다. ㅋㅋㅋㅋㅋㅋㅋㅋ 감탄의 연속 ...

내 코드도 언젠가는 유연해지길 기대한다.

참고