이번 포스팅에선 JUnit 5의 테스트 인스턴스에 대해 알아보겠습니다.
테스트 인스턴스란?
JUnit은 설정된 테스트 단위로 테스트 객체를 만듭니다. 이를 테스트 인스턴스라고 말합니다.
테스트 실행 범위라고 생각하시면 됩니다. 예를 보시면 더 빠른 이해가 가실 거에요.
아래 예제의 테스트를 전부 다 돌리면 어떤 결과가 나올까요?
저 test_1, test_2 메소드 중 하나는 테스트가 성공하지 않을까요?
package com.effortguy.junit5;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class TestInstanceAnnotation {
public int i=0;
@Test
void test_1() {
assertTrue(++i == 1);
}
@Test
void test_2() {
assertTrue(++i == 1);
}
}
하지만 결과를 보면 두 테스트에서 모두 i가 1로 나왔습니다. 왜 이런 결과가 나왔을까요?
JUnit 5는 테스트 인스턴스 생성 기본 단위가 메소드라서 그렇습니다.
아래와 같이 각 메소드 별로 따로 인스턴스가 생성되어 테스트를 한다는 뜻입니다.
메소드 단위로 인스턴스가 만들어지면 테스트 간 영향이 없어 단위 테스트하기에 좋습니다.
public int i=0;
@Test
void test_1() {
assertTrue(++i == 1);
}
public int i=0;
@Test
void test_2() {
assertTrue(++i == 1);
}
음 그럼 만약에 메소드 끼리 영향을 주는 테스트 케이스를 테스트하려면 어떻게 해야 할까요? 그때 사용하는 게 @TestIntance입니다.
@TestInstance
테스트 인스턴스의 생성 단위를 변경하기 위해 사용하는 어노테이션
파라미터명 | 타입 | 설명 |
value | LifeCycle | 테스트 인스턴스 생성 단위 설정 PER_METHOD : 메소드 단위 (기본값) PER_CLASS : 클래스 단위 |
예시
테스트 인스턴스 생성 단위를 클래스로 변경한 예제입니다.
package com.effortguy.junit5;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS;
@TestInstance(value = PER_CLASS)
public class TestInstanceAnnotation {
public int i=0;
@Test
void test_1() {
assertTrue(++i == 1);
}
@Test
void test_2() {
assertTrue(++i == 1);
}
}
결과
@TestInstance 가 PER_METHOD 일 때와 다르게 2번째 테스트가 실패한 것을 볼 수 있습니다. (test_2의 i = 2)
(* 간혹 test_1 테스트가 실패할 수 있습니다. 이유는 JUnit은 테스트 간에 순서를 보장하지 않기 때문입니다.)
@TestInstance 기본값 설정하기
테스트 클래스 전체를 @TestInstance(value = PER_CLASS)로 돌리고 싶다고 한다면 직접 일일이 지정하지 않고 junit-platform.properties에 default 값을 설정해서 해결할 수 있습니다.
junit.jupiter.testinstance.lifecycle.default = per_class
다음 포스팅에선 위에서 잠깐 언급했던 JUnit이 테스트 간에 순서를 보장하지 않는 문제를 해결할 수 있는 @@TestMethodOrder에 대해 알아보겠습니다.
읽어주셔서 감사합니다.
참고
https://junit.org/junit5/docs/current/user-guide/#writing-tests-display-name-generator
댓글