JUnit 5 Architecture
3개의 모듈로 구성
JUnit5 = JUnit Platform + JUnit Jupiter + Junit Vintage
Platform
- JVM에서 테스트 프레임워크를 실행하기 위한 기반 역할
- 이외에도 TestEngine API, Console Launcher, JUnit Platform Suite Engine 제공
- JUnit5 공식문서에서 Platform에 대한 2가지 개념을 정의함
- Container : 테스트 클래스 - 다른 컨테이너나 테스트를 자식으로 갖고 있는 test tree node
- Test : 테스트 메서드 - 실행 결과와 기댓값을 확인하는 test tree node
Jupiter
- JUnit5에서 테스트와 extension 작성을 위한 모델 제공(programming model, extension model)
- Jupiter 서브 프로젝트에서 TestEngine 제공(Platform에서 Jupiter 기반 테스트 실행 목적으로 사용)
- JUnit5 공식문서에서 Jupiter에 대한 3가지 개념을 정의함
- Test Class(Container) : Test 메서드를 최소 1개 이상 가지고 있는 top-level class, static member class, @Nested class - 추상 클래스일 수 없고, 생성자가 하나만 있어야 됨
- Lifecycle Method : @BeforeAll, @AfterAll, @BeforeEach, or @AfterEach이 선언된 메서드
- Test Method : @Test, @RepeatedTest, @ParameterizedTest, @TestFactory, or @TestTemplate이 선언된 인스턴스 메서드
- Lifecycle/Test Method는 public 접근 제어자와 반환 값을 가지지 않음
- @Test를 제외한 나머지 어노테이션이 적용된 Test 메서드는 test tree에 container를 생성함
Vintage (하위 버전 호환)
- Platform에서 JUnit3, JUnit4 기반 테스트 실행을 위한 TestEngine 제공
Test Instance Lifecycle
기본적으로 각 test class의 각 test method가 실행되기 전에 새로운 인스턴스를 생성함(per-method)
- 격리된 테스트 실행
- mutable 테스트 인스턴스 상태로 인한 사이드 이펙트 방지
per-class 테스트 인스턴스 생성
- @TestInstance(Lifecycle.PER_CLASS) 선언
- 인스턴스 메서드에 @BeforeAll, @AfterAll 선언이 가능해짐
Test Class, Test Method
class StandardTests {
@BeforeAll
static void initAll() {
}
@BeforeEach
void init() {
}
@Test
void succeedingTest() {
}
@Test
void failingTest() {
fail("a failing test");
}
@Test
@Disabled("for demonstration purposes")
void skippedTest() {
// not executed
}
@Test
void abortedTest() {
assumeTrue("abc".contains("Z"));
fail("test should have been aborted");
}
@AfterEach
void tearDown() {
}
@AfterAll
static void tearDownAll() {
}
}
@Disabled : 클래스와 메서드에 선언 가능, 테스트를 실행하지 않음
Tagging, Filtering
태그는 테스트를 마킹하고 필터링하는 목적으로 사용함
특징
- tag의 값이 null이거나 blank이면 안됨
-
!, &, 연산자를 사용할 수 있음 - 필터링
@Tag("oauth2")
@Tag("dev")
class OAuth2DevTest {
}
Assertions
- assertEquals
- assertNotEquals
- assertTrue
- assertFalse
- assertAll
- assertThrows
- assertTimeout
- assertTimeoutPreemptively
Extensions
의존성 주입 Extensions
Junit을 사용해서 의존성 주입을 할 수 있지만 대부분의 경우 외부 Extension 사용
@ExtendWith(Mockito.class)
@ExtendWith(SpringExtension.class)
class MyTest {
@Mock
private MyService myService;
@Autowired
private MyRepository myRepository;
@Test
void test() {
// ...
}
}
With Gradle
// test case를 src/test/java 하위에 두고, gradle test 실행
dependencies {
testImplementation('org.junit.jupiter:junit-jupiter-api:5.7.0')
testRuntimeOnly('org.junit.jupiter:junit-jupiter-engine:5.7.0')
}
// JUnit Platform enable
tasks.named('test', Test) {
useJUnitPlatform()
}
Junit5 Annotation, Composed Annotations
코어 어노테이션 위치 : junit-jupiter-api 모듈의 org.junit.jupiter.api 패키지
JUnit5 어노테이션은 메타 어노테이션으로 사용 가능 -> 복합 어노테이션으로 재정의
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Tag("fast")
@Test
public @Interface FastTest() {
}
@FastTest
void oneTest() {
}