[JAVA] - 입력 테스트

김주형·2022년 11월 29일
0

자라기

목록 보기
19/22

🙇🏻‍♂️Reference


입력 받는 기능을 테스트해야 하는 경우

테스트 실행 후 read-only 상태인 콘솔을 조작하지 못해 무한 대기하거나, 값이 할당되지 않았기 때문에 NullPointerException을 맞이하여 프로덕션 코드를 진행하지 못하는 문제가 있었습니다.

public String putReadLine() {
        System.out.println(PUT.render());
        return Console.readLine();
    }
    @Test
    public void 숫자_입력_받기(){

        String expect = "123";
        String actual = inputView.putReadLine();


        assertEquals(expect, actual);

    }
}

단위 테스트를 진행하면서 프로덕션 코드를 개선해나기 위해 노력해보았습니다.


setIn()

System 클래스의 setIn()이라는 기능이 있습니다.

    public static void setIn(InputStream in) {
        checkIO();
        setIn0(in);
    }
  • 표준 입력 스트림을 전달받습니다.
  • 재할당해도 괜찮은지 확인합니다.
  • 괜찮다면 전달받은 InputStream 타입 매개변수를 할당합니다.

InputStream

  • InputStream은 추상 클래스입니다.
  • byte InputStream을 나타내는 모든 구현체의 상위 클래스입니다.
  • 적절한 구현체를 선택해야 합니다.

This abstract class is the superclass of all classes representing an input stream of bytes.
Applications that need to define a subclass of InputStream must always provide a method that returns the next byte of input.
시작 시간:
1.0
관련 주제:
BufferedInputStream, ByteArrayInputStream, DataInputStream, FilterInputStream, read(), OutputStream, PushbackInputStream
작성자:
Arthur van Hoff

ByteArrayInputStream

public class Console {
    private static Scanner scanner;

    private Console() {
    }

    public static String readLine() {
        return getInstance().nextLine();
    }
  • 문자열 입력 받는 기능을 구현해야 하는 상황

  • BufferedInputStream, DataInputStream은 String으로 변환하는데 감 잡기가 힘들었습니다.

  • getBytes()를 사용하면 문자열을 바이트 형태로 인코딩하여 배열로 저장할 수 있다고 합니다.

  •     /**
         * Encodes this {@code String} into a sequence of bytes using the
         * platform's default charset, storing the result into a new byte array.
         *
         * <p> The behavior of this method when this string cannot be encoded in
         * the default charset is unspecified.  The {@link
         * java.nio.charset.CharsetEncoder} class should be used when more control
         * over the encoding process is required.
         *
         * @return  The resultant byte array
         *
         * @since      1.1
         */
        public byte[] getBytes() {
            return StringCoding.encode(coder(), value);
        }
  • ByteArrayInputStream 클래스를 구현체로 선택했습니다.

  • 혹시 모를 변경을 위해 정적 팩토리를 참고하여 반환 객체를 자유롭게 선택할 수 있는 구조를 만들었습니다.

    public static InputStream setReadLine(String readLine) {
        return new ByteArrayInputStream(readLine.getBytes());
    }
  • 테스트 시도 (결과는 성공)
    @Test
    public void 숫자_입력_받기(){

        InputStream readLine = setReadLine("926"); 
        System.setIn(readLine);

        String expect = "926";
        String actual = inputView.putReadLine();

        assertEquals(expect, actual);
    }
}
  • Console.readLine()을 디버깅한 코드를 보면
    private static Scanner getInstance() {
        if (Objects.isNull(scanner) || isClosed()) {
            scanner = new Scanner(System.in);
        }
        return scanner;
    }

new Scanner(System.in)에 들어갔어야 할 코드가
System.setIn(setReadLine)으로 대체되었음을 유추할 수 있는 것 같습니다.

profile
왔을때보다좋은곳으로

0개의 댓글