JUnit 5 애노테이션
JUnit 5 애노테이션
테스트를 작성하다 보면 "이 메서드에 @Test만 붙이면 되는 거지?" 하는 순간이 한 번쯤 있죠. 그런데 JUnit Jupiter에서 테스트를 구성하고 확장하려면 딱 하나의 애노테이션이 아니라 여러 애노테이션을 역할에 맞게 조합해서 쓰게 돼요. 이 페이지에서는 JUnit Jupiter가 기본으로 제공하는 애노테이션을 하나씩 짚어볼게요.
본문
JUnit Jupiter는 테스트를 구성하고 프레임워크를 확장하기 위한 애노테이션을 지원해요. 특별한 언급이 없는 한, 모든 핵심 애노테이션은 junit-jupiter-api 모듈의 org.junit.jupiter.api 패키지에 들어 있어요.
이제 각 애노테이션이 무엇을 뜻하는지 살펴볼게요.
@Test— 메서드가 테스트 메서드임을 나타내요. JUnit 4의@Test와 달리 속성을 선언하지 않아요. JUnit Jupiter의 테스트 확장은 각자 전용 애노테이션으로 동작하기 때문이죠. 오버라이드되지 않는 한 이런 메서드는 상속돼요.@ParameterizedTest— 메서드가 파라미터화 테스트임을 나타내요. 오버라이드되지 않는 한 상속돼요.@RepeatedTest— 메서드가 반복 테스트를 위한 테스트 템플릿임을 나타내요. 오버라이드되지 않는 한 상속돼요.@TestFactory— 메서드가 동적 테스트를 위한 테스트 팩토리임을 나타내요. 오버라이드되지 않는 한 상속돼요.@TestTemplate— 메서드가 등록된 provider가 돌려준 호출 컨텍스트 개수만큼 여러 번 호출되도록 설계된 테스트 케이스의 템플릿임을 나타내요. 오버라이드되지 않는 한 상속돼요.@TestClassOrder— 애노테이션이 붙은 테스트 클래스에서@Nested테스트 클래스의 실행 순서를 구성할 때 써요. 이런 애노테이션은 상속돼요.@TestMethodOrder— 애노테이션이 붙은 테스트 클래스의 테스트 메서드 실행 순서를 구성할 때 써요. JUnit 4의@FixMethodOrder와 비슷하죠. 성격상 상속돼요.@TestInstance— 애노테이션이 붙은 테스트 클래스의 테스트 인스턴스 라이프사이클을 구성해요. 상속돼요.@DisplayName— 테스트 클래스나 테스트 메서드에 사용자 지정 표시 이름을 선언해요. 상속되지는 않아요.@DisplayNameGeneration— 테스트 클래스에 사용자 지정 표시 이름 생성기를 선언해요. 상속돼요.@BeforeEach— 현재 클래스의 각@Test,@RepeatedTest,@ParameterizedTest,@TestFactory메서드 실행 전에 실행해야 함을 나타내요. JUnit 4의@Before에 해당하죠. 오버라이드되지 않는 한 상속돼요.@AfterEach— 현재 클래스의 각 테스트 메서드 실행 후에 실행되어야 함을 나타내요. JUnit 4의@After에 해당해요. 오버라이드되지 않는 한 상속돼요.@BeforeAll— 현재 최상위 또는@Nested테스트 클래스의 모든 테스트 메서드 실행 전에 실행되어야 함을 나타내요. JUnit 4의@BeforeClass에 해당하고, "per-class" 테스트 인스턴스 라이프사이클을 쓰지 않는 한static이어야 해요. 오버라이드되지 않는 한 상속돼요.@AfterAll— 현재 최상위 또는@Nested테스트 클래스의 모든 테스트 메서드 실행 후에 실행되어야 함을 나타내요. JUnit 4의@AfterClass에 해당하고, "per-class" 라이프사이클을 쓰지 않는 한static이어야 해요. 오버라이드되지 않는 한 상속돼요.@ParameterizedClass— 클래스가 파라미터화 클래스임을 나타내요. 상속돼요.@BeforeParameterizedClassInvocation— 파라미터화 클래스의 각 호출 전에 한 번 실행되어야 하는 메서드를 나타내요. 오버라이드되지 않는 한 상속돼요.@AfterParameterizedClassInvocation— 파라미터화 클래스의 각 호출 후에 한 번 실행되어야 하는 메서드를 나타내요. 오버라이드되지 않는 한 상속돼요.@ClassTemplate— 클래스가 등록된 provider가 돌려준 호출 컨텍스트 개수만큼 여러 번 실행되도록 설계된 테스트 클래스의 템플릿임을 나타내요. 상속돼요.@Nested— 클래스가 비정적 중첩 테스트 클래스임을 나타내요. 상속되지는 않아요.@Tag— 클래스 또는 메서드 수준에서 테스트 필터링용 태그를 선언할 때 써요. TestNG의 테스트 그룹이나 JUnit 4의 Categories와 비슷하죠. 클래스 수준에서는 상속되고 메서드 수준에서는 상속되지 않아요.@Disabled— 테스트 클래스나 테스트 메서드를 비활성화할 때 써요. JUnit 4의@Ignore와 비슷하고, 상속되지는 않아요.@AutoClose— 필드가 테스트 실행 후 자동으로 닫힐 리소스임을 나타내요. 필드는 상속돼요.@Timeout— 테스트, 테스트 팩토리, 테스트 템플릿 또는 라이프사이클 메서드가 정해진 시간을 초과하면 실패 처리할 때 써요. 상속돼요.@TempDir— 테스트 클래스 생성자, 라이프사이클 메서드 또는 테스트 메서드의 필드 주입이나 파라미터 주입으로 임시 디렉터리를 공급할 때 써요.org.junit.jupiter.api.io패키지에 있고, 필드는 상속돼요.@ExtendWith— 확장을 선언적으로 등록할 때 써요. 상속돼요.@RegisterExtension— 필드를 통해 확장을 프로그래밍 방식으로 등록할 때 써요. 필드는 상속돼요.
일부 애노테이션은 아직 실험적일 수 있어요. 자세한 내용은 Experimental APIs 표를 참고하면 돼요.
메타 애노테이션과 합성 애노테이션
JUnit Jupiter 애노테이션은 메타 애노테이션으로 쓸 수 있어요. 즉, 우리가 직접 만든 합성 애노테이션을 정의하면 그 메타 애노테이션의 의미를 자동으로 물려받는다는 뜻이죠.
예를 들어 코드베이스 곳곳에서 @Tag("fast")를 복사·붙여넣기 대신, @Fast라는 사용자 정의 합성 애노테이션을 만들어 쓸 수 있어요. @Fast는 @Tag("fast")를 대체하는 드롭인으로 동작하죠.
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.jupiter.api.Tag;
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Tag("fast")
public @interface Fast {
}
아래는 @Fast 애노테이션을 사용하는 @Test 메서드예요.
@Fast
@Test
void myFastTest() {
// ...
}
한 발 더 나아가 @Tag("fast")와 @Test를 동시에 대체하는 @FastTest 애노테이션을 도입할 수도 있어요.
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Tag("fast")
@Test
public @interface FastTest {
}
JUnit은 다음 메서드를 "fast" 태그가 붙은 @Test 메서드로 자동으로 인식해요.
@FastTest
void myFastTest() {
// ...
}
더 알아보기
- JUnit 5 어서션 — 검증을 위한 assertion 메서드 모음
- JUnit 5 태깅과 필터링 —
@Tag를 실제 테스트 실행에 어떻게 적용하는지 - JUnit 5 파라미터화 테스트 —
@ParameterizedTest·@ParameterizedClass의 다양한 인자 소스 - JUnit 5 확장 모델 —
@ExtendWith·@RegisterExtension이 다루는 확장 개념