프로젝트/우테코 6기

[1주차/숫자야구] 2. 테스트코드로 입력에 대한 예외 처리 하기

zangsu_ 2023. 10. 21. 14:40

Player 클래스에서 Consoles 클래스로 사용자의 입력을 처리하고, 잘못된 입력에 대해선 IllegalArgumentException을 발생시켜 주었다.

이제, 내 로직이 예상과 같이 동작하는지 확인하기 위해 테스트 코드를 작성할 차례이다.

 

그런데, 테스트 코드를 실행할 때 마다 직접 입력을 넣어주는 것은 비효율적이기에, 테스트코드 자체적으로 사용자의 입력을 대신할 입력 처리를 해 주어야 했다.

 

처음 시도했던 것은 System.setIn() 메서드를 통해 직접 입력을 처리해 주는 것이었다. 그런데, setIn() 메서드가 익숙하지 않은 탓인지, 첫 번째로 실행되는 테스트를 제외한 모든 테스트가 입력을 정상적으로 처리해 주지 못했다.

즉, Consoles.nextLine()을 통해 값을 가지고 와야 했는데, NoSuchElementException이 발생했다.

 

그래서, 입력을 받아 특정 기능을 제공하는 메서드를

1. 입력을 처리하는 메서드

2. 특정 기능을 처리하는 메서드

의 두 단계로 분리하기로 했다.

콘솔의 입력 값을 String 파라미터로 전달받는 메서드를 오버로딩 하여 기능을 분리하였다.

 

분리 전

public List<Integer> getInput() throws IllegalArgumentException {
    String input = Console.readLine();        
    //== 구현 로직 ==//
}

분리 후

public List<Integer> getInput() throws IllegalArgumentException {
    String input = Console.readLine();
    return getInput(input);
}

public List<Integer> getInput(String input) throws IllegalArgumentException {
    //== 구현 로직 ==//
}

 

위와 같이 기능을 분리해 주면서, 테스트 코드에서는 getInput(String input) 메서드를 사용해 직접 입력 값을 넣어 테스트를 진행할 수 있었고, 실제 로직에서는 getInput() 메서드를 사용해 Console의 입력을 받을 수 있었다.

//비즈니스 코드
public void play() {
    //== 코드 생략 ==//
    
    List<Integer> input = player.getInput();
    	//getInput() 사용
    
    //== 코드 생략 ==//
}

// 테스트 코드
@Test
public void input_must_not_duplicated() throws Exception {
    //given
    //when
    Assertions.assertThatThrownBy(
                    () ->
                            player.getInput("111"), // getInput(String input) 사용
                    Player.INPUT_MUST_NOT_DUPLICATED_EXCEPTION)
            .isInstanceOf(IllegalArgumentException.class);
    //then
}