Extension
Extension은 테스트 실행 전후로 무언가 처리를 하고 싶을 때 사용한다.
위와 같이 언제 실행될 것인지 구체적으로 정할 수 있으며 Interface로 구성되어 implements를 선언 후 메서드를 작성해주어야 한다.
주요 인터페이스
- AfterAllCallback : 모든 테스트 종료 후 실행 (가장 나중에 실행된다.)
- AfterEachCallback : @AfterEach 적용된 메서드 종료 후 실행
- AfterTestExecutionCallback : 각 테스트가 종료 후 실행
- BeforeAllCallback - @BeforeAll 적용된 메서드 전에 실행(가장 먼저 실행된다.)
- BeforeEachCallback - @BeforeEach 적용된 메서드 종료 후 실행
- BeforeTestExecutionCallback - 각 테스트가 실행되기 직전에 실행
테스트 클래스에 Extension 적용 방법
1. @ExtendWith : 클래스에 적용하여 Extension 등록
@ExtendWith(FindSlowTestExtension.class)
public class ExtensionTest
2. @RegisterExtension : 필드에 적용하여 Extension 등록
@RegisterExtension
static FindSlowTestExtension findSlowTestExtension = new FindSlowTestExtension(3000L);
더 많은 방법이 있지만 크게 위 2가지를 사용하여 적용한다.
@ExtendWith를 적용할 경우 기본 생성자로 만들어지기 때문에 초기화 시 필드값을 넣어주어야 한다면 @RegisterExtension 을 적용하면 된다.
주요 인터페이스 순서 예시
OrderTestExtension.java
package me.hoon.tdd.practice.extension;
import org.junit.jupiter.api.extension.*;
public class OrderTestExtension implements BeforeAllCallback, BeforeEachCallback, BeforeTestExecutionCallback, AfterAllCallback, AfterEachCallback, AfterTestExecutionCallback {
@Override
public void beforeAll(ExtensionContext extensionContext) throws Exception {
System.out.println("BeforeAllCallback 실행");
}
@Override
public void beforeEach(ExtensionContext extensionContext) throws Exception {
System.out.println("BeforeEachCallback 실행");
}
@Override
public void beforeTestExecution(ExtensionContext context) throws Exception {
System.out.println("beforeTestExecution 실행");
}
@Override
public void afterAll(ExtensionContext extensionContext) throws Exception {
System.out.println("AfterAllCallback 실행");
}
@Override
public void afterEach(ExtensionContext extensionContext) throws Exception {
System.out.println("AfterEachCallback 실행");
}
@Override
public void afterTestExecution(ExtensionContext context) throws Exception {
System.out.println("afterTestExecution 실행");
}
}
주요 인터페이스의 메서드를 Overried 하여 테스트 실행 시 메시지를 출력하게 하였다.
ExtensionTest.java
package me.hoon.tdd.practice.extension;
import org.junit.jupiter.api.*;
import org.junit.jupiter.api.extension.ExtendWith;
@ExtendWith(OrderTestExtension.class)
public class ExtensionTest {
@BeforeAll
static void beforeAll() {
System.out.println("@BeforeAll 실행");
}
@AfterAll
static void afterAll() {
System.out.println("@AfterAll 실행");
}
@BeforeEach
void beforeEach() {
System.out.println("@beforeEach 실행");
}
@AfterEach
void afterEach() {
System.out.println("@AfterEach 실행");
}
@Test
void test1() {
System.out.println("test1 메서드 실행");
}
@Test
void test2() {
System.out.println("test2 메서드");
}
@Test
void test3() {
System.out.println("test3 메서드");
}
}
테스트 메서드 구현
실행 순서
BeforeAllCallback 실행
@BeforeAll 실행
----------------------------------------
BeforeEachCallback 실행
@beforeEach 실행
beforeTestExecution 실행
test1 메서드 실행
afterTestExecution 실행
@AfterEach 실행
AfterEachCallback 실행
----------------------------------------
BeforeEachCallback 실행
@beforeEach 실행
beforeTestExecution 실행
test2 메서드
afterTestExecution 실행
@AfterEach 실행
AfterEachCallback 실행
----------------------------------------
BeforeEachCallback 실행
@beforeEach 실행
beforeTestExecution 실행
test3 메서드
afterTestExecution 실행
@AfterEach 실행
AfterEachCallback 실행
----------------------------------------
@AfterAll 실행
AfterAllCallback 실행
한번씩 실행 (가장먼저 실행)
BeforeAllCallback 실행
@BeforeAll 실행
각 테스트마다 실행
BeforeEachCallback 실행
@beforeEach 실행
beforeTestExecution 실행
test1~3 메서드 실행
afterTestExecution 실행
@AfterEach 실행
AfterEachCallback 실행
한번씩 실행 (모든 테스트 종료 후 실행)
@AfterAll 실행
AfterAllCallback 실행
ExtensionContext
상속 받은 모든 메서드에는 ExtensionContext 가 매개변수로 있다.
private void getExtensionContextInfo(ExtensionContext context) {
//실행 중인 class명
System.out.println(context.getRequiredTestClass().getName());
//실행 중인 method명
System.out.println(context.getRequiredTestMethod().getName());
}
실행 결과
me.hoon.tdd.practice.extension.ExtensionTest
test1
위와 같이 클래스의 정보를 담고 있으며 Reflection을 사용했을 때 클래스의 정보를 가져올 수 있는 것처럼 ExtensionContext에서도 가져올 수 있으며 필요시 테스트 하는데 활용 할 수도 있다.
또한 ExtensionContext.Store를 통해 테스트마다 특정한 값을 전달할 수 있다.
@Override
public void beforeEach(ExtensionContext context) throws Exception {
System.out.println("BeforeEachCallback 실행");
ExtensionContext.Store store = getStore(context);
//값 저장
store.put("key", "value");
}
@Override
public void afterEach(ExtensionContext context) throws Exception {
System.out.println("AfterEachCallback 실행");
ExtensionContext.Store store = getStore(context);
//값 얻기
System.out.println(store.get("key"));
}
private static ExtensionContext.Store getStore(ExtensionContext context) {
String testClassName = context.getRequiredTestClass().getName();
String testMethodName = context.getRequiredTestMethod().getName();
return context.getStore(ExtensionContext.Namespace.create(testClassName, testMethodName));
}
실행 결과
BeforeEachCallback 실행
test1 메서드 실행
AfterEachCallback 실행
value
store을 사용해서 key, value 형태로 저장이 가능하고 저장된 값을 얻어올 수 있다.
마치 ThreadLocal 처럼 사용이 가능하며 별도로 자원을 해제할 필요는 없다.