현재노트

asserts-core, junit-jupiter 를 활용한 단위테스트 본문

Back/testCode

asserts-core, junit-jupiter 를 활용한 단위테스트

현재노트 2023. 6. 8. 14:17

테스트는 테스트 대상 범위나 성격에 때라 E2E 테스트, Integration Test(통합 테스트), Unit Test(단위 테스트) 등 3가지로 구분합니다.

 

 

현재 여기 페이지에서는 단위 테스트에 대해서 설명을 할것입니다.

단위테스트는 클래스 범주 내에서 작은 단위(함수 단위)의 기능에 대한 유효성을 검증하는 테스트입니다.

매우 간단하고 명확하며 빠르게 실행된다는 특징이 있습니다.

 

 

본 문서는 asserts-core, junit-jupiter를 사용하여 테스트 코드를 작성하였습니다.

 

dependencies {
    testImplementation 'org.assertj:assertj-core:3.22.0'
    testImplementation 'org.junit.jupiter:junit-jupiter:5.8.2'
}

 

테스트 코드에 사용할 코드는 Operator 라는 enum만 사용하여 예시를 만들도록 하겠습니다.

기능은 연산이 가능한 계산기 프로그램입니다.

 

import java.util.Arrays;
import java.util.function.ToIntBiFunction;

public enum Operator {

    PLUS("+", (a,b) -> a + b),
    MINUS("-", (a,b) -> a - b ),
    MULTIPLY("*", (a,b) -> a * b),
    DIVIDE("/", (a,b) -> {
        if(b == 0) {
            throw new RuntimeException("0으로 나눌수 없습니다.");
        }
        return a / b;
    });

    private final String symbol;
    private final ToIntBiFunction<Integer, Integer> operate;

    Operator(String symbol, ToIntBiFunction<Integer, Integer> operate) {
        this.symbol = symbol;
        this.operate = operate;
    }

    public int operate(int a, int b) {
        return operate.applyAsInt(a, b);
    }

    public static Integer operate(String symbol, int a, int b) {
        return Arrays.stream(values())
                .filter(it -> it.symbol.equals(symbol))
                .findFirst()
                .orElseThrow(() -> new IllegalArgumentException("없는 심볼입니다..."))
                .operate(a, b);
    }

}

 

테스트코드는 일반적으로 @DisplayName으로 어떤 테스트를 하는지를 작성을 하며, assertThat을 사용하여 원하는 결과를 확인합니다.

 

 

import static org.assertj.core.api.Assertions.assertThat;

class OperatorTest {

    @DisplayName("두개의 합이 2로 반환한다.")
    @Test
    void plus() {
        int result = Operator.operate("+", 1, 1);

        assertThat(result).isEqualTo(2);
    }
}

 

인텔리제이 기준으로 테스트를 실행후, 실행 결과를 확인할 수 있습니다.

 

 

만약 원하는 결과 값과 실행결과가 다를 경우, Tests failed 가 뜨고, 실패한 이유가 콘솔로 보여주게 됩니다.

 

 

테스트 코드에는 원하는 결과값을 원하는 경우도 있지만 에러를 테스트하는 경우도 있다.

위에 예제에서 +, -, *, / 네개의 연산자 말고 다른 경우가 입력이 되게 된다면 에러를 반환한다.

이것도 테스트 코드에서 테스트가 가능하다.

 

    @DisplayName("존재하지 않는 연산자일 경우 에러를 반환한다.")
    @Test
    void operatorException() {

        assertThatThrownBy(() -> Operator.operate("@", 1, 1))
                .isInstanceOf(IllegalArgumentException.class)
                .hasMessage("없는 심볼입니다...");

    }

 

 
 

assertThatThrownBy로 에러가 발생할 메소드를 넣으면 InstanceOf 정의된 에러가 맞다면, 테스트는 성공으로 표시가 된다.

또한, 자주 에러가나는 IllegalArgumentException이나 IoException같은 경우는 정의 된 메소드가 있어 편하게 에러를 검증할 수 있다.

 

    @DisplayName("존재하지 않는 연산자일 경우 에러를 반환한다.")
    @Test
    void operatorException2() {

        assertThatIllegalArgumentException().isThrownBy(() -> {
            Operator.operate("@", 1, 1);
        }).withMessage("없는 심볼입니다...");

    }

 

만약에 +, -, *, / 를 모두 테스트하고 싶으면 어떻게 할까?

모든 메소드를 넣고 검증을 하면 되는걸까? 그럴경우에는 중복되게 사용되는 코드들이 생겨나 코드를 이해하는데도 어려움이 생길 여지가 충분히 있다.

 

그래서 junit-jupiter-parameters 라는 라이브러리에서는 @ParameterizedTest를 사용하여 반복하여 테스트를 할 수 있게 도움을 주고 있다.

 

methodSource는 입력값들을 메소드에 정의시켜 입력값을 넣어주는 역할을 하고 있다.

이렇게 되면 사칙연산을 한번에 모두 테스트를 할 수 있어 테스트 코드 작성하는데 시간을 줄일 수 있다.

 

    @ParameterizedTest
    @MethodSource("parameters")
    void operate(int a, String symbol, int b, int expected) {
        int result =  Operator.operate(symbol, a, b);

        assertThat(result).isEqualTo(expected);
    }

    private static Stream<Arguments> parameters() {
        return Stream.of(
               arguments(1, "+", 1, 2),
                arguments(2, "-", 1, 1),
                arguments(3, "*", 4, 12),
                arguments(4, "/", 2, 2)
        );
    }
Comments