728x90
이전 글
이번에는 이전에 공부한 내용을 바탕으로 활용한 내용을 설명하겠다
@ParameterizedTest
//Class Car
public void moveOrStop() {
if (isMove()) {
move++;
}
}
private boolean isMove() {
int randomNumber = Randoms.pickNumberInRange(0, 9);
if (randomNumber >= 4) {
return true;
}
return false;
}
@ParameterizedTest
@CsvSource(value = {"0, 0", "1, 0", "2, 0", "3, 0", "4, 1", "5, 1", "6, 1", "7, 1", "8, 1", "9, 1"})
@DisplayName("랜덤값에 따라 자동차 전진/멈추기 테스트")
void moveOrStop_동작_확인(int randomValue, int expected) {
try (MockedStatic<Randoms> mock = Mockito.mockStatic(Randoms.class)) {
mock.when(() -> Randoms.pickNumberInRange(anyInt(), anyInt())).thenReturn(randomValue);
Car car = new Car("붕붕카");
car.moveOrStop();
assertThat(car.getPath()).isEqualTo(expected);
}
}
- Randoms.pickNumberInRange에서 randomValue가 나올 경우 결과값에 대해 테스트한다
- @ParameterizedTest를 붙이고
- @CsvSource 부분에서 테스트메서드 인자로 들어갈 값을 지정한다
- "1, 0"의 경우 randomValue에 1이 들어가고, expected에 0이 들어간다
- try resource문에서 Randoms에 대한 static mock객체를 생성한다
- try문 내부에서는 Randoms의 pickNumberInRange(anyInt(), anyInt()) 메서드를 호출했을 때 randomValue를 return하도록 mock을 설정해준다.
- Car를 새로 만들고, moveOrStop() 을 호출하면 내부에서 Randoms.pickNumberInRange 함수를 호출한다
- 그리고 car.getPath()를 호출했을 때 나오는 값이 expected인지 확인한다
- 다음과 같이 CsvSource에 넣은 값으로 반복하여 테스트가 진행된다
- 묶여서 나오는 것도 하나의 장점이다
@Nested
class InputValidatorTest {
private InputValidator inputValidator = new InputValidator();
@DisplayName("자동차 이름 검증")
@Nested
class ValidateCarNames {
@Test
@DisplayName("정상동작")
void good_case() {
//when
String goodCarNamesInput = "카,붕붕카,타요버스,시내버스,토마스버스,'";
//then
assertDoesNotThrow(() -> {
inputValidator.validateCarNames(goodCarNamesInput);
});
}
@ParameterizedTest
@CsvSource(value = {"'붕붕카,타요버스,'", "'붕붕카,'", "',붕붕카'", "'붕붕카,,타요버스'"})
@DisplayName("쉼표구분 예외 발생")
void 쉼표구분_예외_발생(String input) {
assertThatThrownBy(() -> inputValidator.validateCarNames(input))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("자동차 이름의 길이는 1이상 5이하여야 합니다");
}
}
- @Nested로 관련있는 테스트를 한 곳에 묶었다
- "붕붕카,타요버스" 라는 String 자체를 input에 넣기위해 " 안에 ' 를 넣었다
- @Nested가 된 테스트들은 다음과 같이 묶여서 테스트된다
이렇게 자동차 이름 입력에 쉼표구분 테스트와 정상동작 테스트가 묶여서 나오는 걸 볼 수 있다
Console.readLine() 관련 테스트
class ConsoleInputTest {
static InputValidator inputValidator;
static ConsoleInput consoleInput;
@BeforeAll
static void init() {
inputValidator = mock(InputValidator.class);
consoleInput = new ConsoleInput(inputValidator);
when(inputValidator.validateCarNames(ArgumentMatchers.anyString()))
.thenReturn(true);
doNothing().when(inputValidator).validateMoveCount(ArgumentMatchers.anyString());
}
@AfterEach
void clearSystemIn() {
Console.close();
}
@DisplayName("자동차 이름 입력")
@Test
void goodCase() {
//given
byte[] buf = "붕붕카,타요버스,시내버스,토마스버스".getBytes();
System.setIn(new ByteArrayInputStream(buf));
//when
List<String> carNames = consoleInput.getCarNames();
//then
assertThat(carNames).contains("붕붕카", "타요버스", "시내버스", "토마스버스");
assertThat(carNames).containsExactly("붕붕카", "타요버스", "시내버스", "토마스버스");
}
}
- 테스트 메서드를 실행하기 전 ConsoleInput이 가지고 있는 InputValidator를 mock으로 설정하여 아무동작도 수행하지 않도록 한다
- 그다음 System.setIn 을 이용하여 "붕붕카,타요버스,시내버스,토마스버스"를 시스템의 인풋으로 넣어준다(콘솔 입력값으로 넣어준다고 생각하면 된다)
- 그리고 consoleInput.getCarNames()를 호출한다
- System.in을 위에서 설정해줬기 때문에 해당 값을 받아와 List<String>을 만들어 반환한다
- 해당 리스트에 순서에 맞게 "붕붕카", "타요버스", "시내버스", "토마스버스"가 포함되어있는지 검증한다
System.out.print 관련 테스트
class ConsoleOutputTest {
private OutputStream captor;
private Output output;
@BeforeEach
void init() {
captor = new ByteArrayOutputStream();
System.setOut(new PrintStream(captor));
output = new ConsoleOutput();
}
@AfterEach
void cleanBuffer() {
System.out.flush(); //출력버퍼 비우기
}
@Test
@DisplayName("자동차 이름 입력 문구 출력")
void print_car_names_input_request() {
output.printCarNamesInputRequest();
assertThat(getOutput()).contains("경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)");
}
String getOutput() {
return captor.toString();
}
}
- 메서드 실행 전, System.out으로 나올 값의 출구를 capor에 저장하는 새로운 PrintStream으로 설정한다
- 그리고 output을 실행하여 captor에 system.out으로 나오는 값을 받는다
- 받은 값에 "경주할 자동차 이름을 입력하세요.(이름은 쉼표(,) 기준으로 구분)"가 포함되어 있는지 확인한다
- 메서드를 끝내면 System.out에 들어있는 값을 싹 비워준다 (다른 테스트를 진행하기 위함)
assertThatThrownBy
assertThatThrownBy(() -> inputValidator.validateMoveCount(input))
.isInstanceOf(IllegalArgumentException.class)
.hasMessageContaining("이동 횟수는 아홉 자릿수 이내여야 합니다.");
- inputValidator객체의 validateMoveCount(input) 메서드를 실행했을 때 예외가 발생하는 지 확인한다
- 예외가 발생해야 정상
- 그리고 그 예외가 IllegalArgumentException인지 확인한다
- 또한 예외에 "이동 횟수는 아홉 자릿수 이내여야 합니다"가 포함되어있는지 테스트한다
assertDoesNotThrow()
assertDoesNotThrow(() -> {
inputValidator.validateMoveCount(goodMoveCountInput);
});
- 해당 코드를 수행했을 때 예외가 발생하지 않는지 테스트한다
728x90
'프로그래밍 언어 > Java' 카테고리의 다른 글
[JAVA] 상수와 enum 공부하기1 (0) | 2023.11.07 |
---|---|
[JAVA] 상수를 private static final로 선언하는 이유 (0) | 2023.11.07 |
[JAVA] 클래스 내부 속성으로 가지고 있는 객체를 mock으로 설정하는 방법: @InjectMock이 동작하지 않는 이유 (0) | 2023.11.01 |
[우테코] 2주차 Test코드 분석 - NsTest, assertj, JUnit (0) | 2023.10.30 |
[JAVA] 문자열 양쪽 공백을 제거하는 trim과 strip 비교 (0) | 2023.10.29 |