로또 미션을 진행하면서, 당첨된 등수를 enum 타입으로 표현해봤다.
class LottoRankTest {
@ParameterizedTest
@DisplayName("등수를 올바르게 결정하는지 확인")
@CsvSource(value = {"6:false:FIRST", "5:true:SECOND", "5:false:THIRD", "4:false:FOURTH",
"4:true:FOURTH", "3:true:FIFTH", "3:false:FIFTH"}, delimiter = ':')
void valueOf(int sameCount, boolean bonus, LottoRank expectedLottoRank) {
LottoRank lottoRank = LottoRank.valueOf(sameCount, bonus);
Assertions.assertThat(lottoRank).isEqualTo(expectedLottoRank);
}
}
위와 같이 테스트를 짜서 각 등수가 올바르게 나오는지 테스트를 했었는데, 원래 RANK_FIRST
로 썼던 변수 이름을 FIRST
와 같은 형식으로 바꾸다보니 해당 테스트가 실패하는 일이 발생했다. 던에 말대로 코드를 작성하려면 맞은 번호, 보너스 번호와 같은지, 등수 정보를 모두 보내줘야 하는데 @CsvSource
로는 하드 코딩을 피할 수 없었다.
새로운 방법을 찾던 중 @MethodSource
를 알게되었다. 복잡한 객체를 넘겨주며 테스트할 때 사용하면 좋다. 사용방법은 아래와 같다.
@ParameterizedTest
@DisplayName("등수를 올바르게 결정하는지 확인")
@MethodSource("rankParameterProvider")
void valueOf(int sameCount, boolean bonus, LottoRank expectedLottoRank) {
LottoRank lottoRank = LottoRank.valueOf(sameCount, bonus);
Assertions.assertThat(lottoRank).isEqualTo(expectedLottoRank);
}
private static Stream<Arguments> rankParameterProvider() {
return Stream.of(
Arguments.arguments(6, false, FIRST),
...
);
}
@MethodSource
에 변수를 스트림으로 제공하는 스태틱 메서드 이름을 작성하면 가져다가 쓸 수 있다. 이름을 따로 지정하지 않으면 Junit이 테스트 메서드와 같은 이름을 찾아서 사용한다.
위와 같이 테스트를 한다면 LottoRank
의 변수 명칭이 바뀔 때 마다 테스트 코드를 수정하지 않아도된다.
추가로 테스트 코드를 작성할 때 검증부(assert/expect)는 하드코딩하는게 좋다
해당 링크에 가면 더 자세하게 나와있다.
검증값에 도메인 로직을 이용한다면, 검증을 안하고 있다고 볼 수 있다.
https://www.baeldung.com/parameterized-tests-junit-5
https://jojoldu.tistory.com/615