[Test] 단위테스트
단위 테스트는 하나의 모듈을 기준으로 독립적으로 진행되는 가장 작은 단위의 테스트이다.
애플리케이션에서 작동하는 하나의 기능 또는 메소드로 이해할 수 있다.
예를 들면 웹 애플리케이션에서 로그인 메소드에 대한 독립적인 테스트가 1개의 단위 테스트가 될 수 있다.
즉, 단위 테스트는 애플리케이션을 구성하는 하나의 기능을 올바르게 작동하는 지 독립적으로 테스트하는 것으로, "어떤 기능이 실행되면 어떤 결과가 나온다." 정도로 테스트를 진행한다.
테스트 코드를 작성한다고 하면 거의 단위 테스트를 의미한다.
통합 테스트는 실제 여러 컴포넌트들 간의 상호작용을 테스트하기 때문에 모든 컴포넌트들이 구동된 상태에서 테스트를 하게 된다.
그렇기에 통합 테스트를 위해서는 캐시나 데이터베이스 등 다른 컴포넌트들과 실제 연결을 해야 하고, 시스템을 구성하는 컴포넌트들이 많아질수록 테스트를 위한 비용(시간)이 상당히 커진다. 반면에 단위 테스트는 해당 부분만 독립적으로 테스트하기 때문에 어떤 코드를 리팩토링하여도 빠르게 문제 여부를 확인할 수 있다.
요즘 Java 단위테스트 작성에는 크게 2가지 라이브러리가 사용된다.
- JUnit5: 자바 단위 테스트를 위한 테스팅 프레임워크
- AssertJ: 자바 테스트를 돕기 위해 다양한 문법을 지원하는 라이브러리
JUnit 만으로도 단위 테스트를 충분히 작성할 수 있다. 하지만 JUnit에서 제공하는 assertEquals()와 같은 메소드는 AssertJ가 주는 메소드에 비해 가독성이 떨어진다. 그렇기 때문에 순수 Java 애플리케이션에서 단위 테스트를 위해 JUnit5와 AssertJ 조합이 많이 사용된다.
예를 들어 다음과 같이 1000원을 주면 1개의 로또를 생성해주는 클래스가 있다고 하자.
1. 로또 번호 갯수 테스트
우선 로또를 생성받기 위해서는 로또 생성기 객체와 금액이 필요하다. 그렇기에 given 단계에서는 LottoNumberGenerator 객체와 금액을 적어주면 된다.
@DisplayName("로또 번호 갯수 테스트")
@Test
void lottoNumberSizeTest() {
// given
final LottoNumberGenerator lottoNumberGenerator = new LottoNumberGenerator();
final int price = 1000;
// when
// then
}
최종적으로 우리가 받은 로또가 6개의 숫자를 갖는지 검증해야 한다. 이에 대한 테스트 코드를 작성하면 다음과 같다.그리고 위와 동일하게 다른 테스트 코드들도 다음과 같이 작성을 할 수 있다.
@DisplayName("로또 번호 갯수 테스트")
@Test
void lottoNumberSizeTest() {
// given
final LottoNumberGenerator lottoNumberGenerator = new LottoNumberGenerator();
final int price = 1000;
// when
final List<Integer> lottoNumber = lottoNumberGenerator.generate(price);
// then
assertThat(lotto.size()).isEqualTo(6);
}
2. 로또 번호 범위 테스트
이번에는 모든 로또 숫자가 1에서 45사이의 숫자인지를 boolean 값으로 검사하므로, AssertJ의 isTrue() 문법이 사용되었다. 그 외에도 isFalse(), isNull(), isNotNull() 등의 메소드가 있다.
@DisplayName("로또 번호 범위 테스트")
@Test
void lottoNumberRangeTest() {
// given
final LottoNumberGenerator lottoNumberGenerator = new LottoNumberGenerator();
final int price = 1000;
// when
final List<Integer> lotto = lottoNumberGenerator.generate(price);
// then
assertThat(lotto.stream().allMatch(v -> v >= 1 && v <= 45)).isTrue();
}
3. 잘못된 로또 금액 테스트
마지막으로 잘못된 금액이 발생한 경우, Runtime Exception이 발생하는 코드에 대해 테스트를 해야 한다. 예외가 발생하는 경우에는 when 단계에서 assertThrows()로 감싸서 처리를 해야 한다.
@DisplayName("잘못된 로또 금액 테스트")
@Test
void lottoNumberInvalidMoneyTest() {
// given
final LottoNumberGenerator lottoNumberGenerator = new LottoNumberGenerator();
final int price = 2000;
// when
final RuntimeException exception = assertThrows(RuntimeException.class, () -> lottoNumberGenerator.generate(price));
// then
assertThat(exception.getMessage()).isEqualTo("올바른 금액이 아닙니다.");
}