테스트 예상값을 하드코딩하지 않고 일급컬렉션으로 지정할 수 있을까?

Hyunta·2022년 2월 28일
0

로또 미션

목록 보기
3/6

로또 미션을 진행하면서, 당첨된 등수를 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 의 변수 명칭이 바뀔 때 마다 테스트 코드를 수정하지 않아도된다.


PS

추가로 테스트 코드를 작성할 때 검증부(assert/expect)는 하드코딩하는게 좋다
해당 링크에 가면 더 자세하게 나와있다.
검증값에 도메인 로직을 이용한다면, 검증을 안하고 있다고 볼 수 있다.

Reference

https://www.baeldung.com/parameterized-tests-junit-5
https://jojoldu.tistory.com/615

profile
세상을 아름답게!

0개의 댓글