사전 준비
Spring Boot 2.2 부터는 JUnit5가 기본으로 포함되어 있기 때문에 별도의 설정이 필요 없습니다. 만약 Spring Boot 2.1 이하 버전 또는 Spring Boot를 사용하지 않는 경우에는 의존성 추가를 해줘야 합니다.
1. web.xml (Maven)
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.5.2</version>
<scope>test</scope>
</dependency>
2. build.gradle (Gradle)
testCompile group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.5.2'
JUnit5 어노테이션
1. @Test
본 어노테이션은 테스트 메소드를 명시하는 어노테이션입니다. 테스트를 위해서는 필수로 작성되어야 하는 어노테이션으로 볼 수 있습니다. Intellij에서 사용하게 되면 @Test 어노테이션을 명시한 메서드 옆에 아래와 같이 실행 버튼이 생성됩니다. 해당 버튼을 누르면 메서드 별로 테스트를 실행할 수 있습니다.
2. @BeforeEach
해당 어노테이션은 각 테스트 메소드마다 시작 전에 실행되는 메소드를 명시하는데 사용됩니다. 테스트를 수행하기 전에 미리 준비되어야 하는 데이터를 생성하는데 주로 사용됩니다. 제가 사용할 때는 서비스 로직을 테스트할 때 사전에 필요한 정보들을 데이터베이스에 삽입하는데 사용했습니다.
3. @AfterEach
본 어노테이션은 각 테스트 메소드가 끝날 때마다 실행되는 메소드를 명시하는데 사용됩니다. 테스트를 수행한 후 사용한 테스트 데이터들을 삭제하거나 원래대로 돌려놓는데 주로 사용됩니다. 제가 Redis의 CRUD 테스트를 하면서 삽입했던 데이터를 삭제할 때 주로 사용했었습니다.
4. @BeforeAll
본 어노테이션은 모든 테스트 메소드가 시작되기 전에 실행되는 메소드를 명시하는데 사용됩니다. JPA Repository 객체를 생성하는데 사용할 수 있습니다. 하지만 일반적으로는 @Autowired를 이용해서 의존성 주입을 하는 것이 좋습니다.
@BeforeAll은 메소드 단위로 테스트할 때는 @BeforeEach와 동일하게 동작합니다. 하지만 클래스 단위로 여러 개의 메소드를 한 번에 테스트하는 경우에 @BeforeAll은 모든 테스트가 시작되기 전 한번만 실행되고, @BeforeEach는 매 테스트가 시작되기 전에 실행되는 차이점이 있습니다.
5. @AfterAll
본 어노테이션은 모든 테스트 메소드가 완전히 끝난 후에 실행되는 메소드를 명시하는데 사용됩니다.
@AfterAll은 실행되는 시점 기준이 모든 테스트 메서드인 점은 @BeforeAll과 동일하지만, @AfterAll은 모든 테스트 메서드가 끝난 후에 한 번만 실행되는 차이점이 있습니다.
6. @Disable
본 어노테이션은 실행되지 말아야 할 테스트 메소드를 명시할 때 사용되는 어노테이션입니다. 일부 테스트 메소드를 실행하지 않아야 할 때 명시하여 테스트를 진행하지 않도록 할 수 있습니다.
하지만 사전 메소드인 @BeforeAll, @AfterAll은 실행되고, @BeforeEach, @AfterEach는 실행되지 않는 특징이 있습니다.
7. @DisplayName
본 어노테이션은 테스트 메소드명이 아닌 지정된 이름으로 메소드명을 표시할 수 있는 어노테이션입니다. @Nested 클래스로 계층을 나누어도 메소드명이 길어지면 여전히 알아보기 힘듭니다. 하지만 본 어노테이션을 사용하면 메소드명을 알아보기 사용자가 원하는대로 바꿀 수 있습니다.
8. @Nested
본 어노테이션은 클래스로 비슷한 테스트 메소드를 묶을 수 있는 어노테이션입니다. 상대적으로 전체적인 코드의 양은 늘어나지만 계층적인 구조로 볼 수 있어 가독성이 좋아집니다. 게다가 클래스로 구분되어 success와 fail을 중복으로 사용해도 문제가 없습니다.
예시
1. 테스트 코드
package com.practice.auth;
import org.junit.jupiter.api.*;
public class Basic {
@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("--------------------------");
System.out.println("@Test : test case 1");
System.out.println("--------------------------");
}
@Test
void test2() {
System.out.println("--------------------------");
System.out.println("@Test : test case 2");
System.out.println("--------------------------");
}
@Test
@Disabled
void test3() {
System.out.println("--------------------------");
System.out.println("@Test : test case 3");
System.out.println("--------------------------");
}
@Nested
public class SubBasic {
@BeforeEach
void beforeEach() {
System.out.println("@BeforeEach - SubBasic");
}
@AfterEach
void afterEach() {
System.out.println("@AfterEach - SubBasic");
}
@Test
void test1() {
System.out.println("--------------------------");
System.out.println("@Test : test case 1 - SubBasic");
System.out.println("--------------------------");
}
@Test
void test2() {
System.out.println("--------------------------");
System.out.println("@Test : test case 2 - SubBasic");
System.out.println("--------------------------");
}
}
}
2. 메소드 단위 테스트 실행 (1개의 메소드)
@Test
void test1() {
System.out.println("--------------------------");
System.out.println("@Test : test case 1");
System.out.println("--------------------------");
}
@BeforeAll은 처음에 한번, @AfterAll은 마지막에 한 번만 실행되는 것을 확인할 수 있습니다.
@BeforeEach는 메소드 단위 테스트 실행 시마다 실행되고, @AfterEach는 끝날 때마다 실행되는 것을 볼 수 있습니다.
3. 클래스 단위 테스트 실행 (4개의 메소드)
@BeforeAll 은 클래스 단위 테스트 실행 시 처음 한번, @AfterAll 은 끝날 때 한번 실행되는 것을 볼 수 있습니다.
하지만 @BeforeEach는 메소드 단위 테스트 실행 시마다 실행되고, @AfterEach는 끝날 때마다 실행되는 것을 볼 수 있습니다.
@Disabled 메소드는 Each 메소드와 테스트 메소드가 실행되지 않는 것을 확인할 수 있습니다.
4. Disable 테스트 실행
@Test
@Disabled
void test3() {
System.out.println("--------------------------");
System.out.println("@Test : test case 3");
System.out.println("--------------------------");
}
"test3" 메소드는 @Disable 메소드로 테스트 로직을 실행하지 않습니다. 하지만 @BeforeAll 메소드와 @AfterAll 메소드는 실행되는 것을 볼 수 있습니다.
5. DisplayName 확인
@Test
@DisplayName("메소드 명시 테스트")
void test4() {
System.out.println("--------------------------");
System.out.println("@Test : test case 4");
System.out.println("--------------------------");
}
"test4" 메소드는 @DisplayName을 이용해 메소드 이름을 명시했습니다. 그래서 왼쪽 테스트 결과창에서 "메소드 명시 테스트" 라고 나오는 것을 볼 수 있습니다.
6. Nested 계층 구조 확인
@Nested
public class SubBasic {
@BeforeEach
void beforeEach() {
System.out.println("@BeforeEach - SubBasic");
}
@AfterEach
void afterEach() {
System.out.println("@AfterEach - SubBasic");
}
@Test
void test1() {
System.out.println("--------------------------");
System.out.println("@Test : test case 1 - SubBasic");
System.out.println("--------------------------");
}
@Test
void test2() {
System.out.println("--------------------------");
System.out.println("@Test : test case 2 - SubBasic");
System.out.println("--------------------------");
}
}
@Nested로 인해 클래스가 분리되어 계층화 구조가 되어 테스트 결과 가독성이 높아졌습니다. 또한 Nested 클래스 별로 Each 메소드를 정의할 수 있어 사전에 더 필요한 작업이 있으면 Nested 클래스에서만 별도로 적용할 수 있습니다.
위와 같이 Nested 클래스의 테스트 메소드는 전, 후로 SubBasic이 붙은 Each 메소드가 더 실행되는 것을 볼 수 있습니다.
'Java > Junit' 카테고리의 다른 글
[Spring] JUnit5 기반 기능 구현해보기 - Repository 단위 테스트 (0) | 2023.08.31 |
---|---|
[Spring] JUnit5 기반 기능 구현해보기 - 구조 설계 (0) | 2023.08.30 |
[Spring] JUnit5 Assertions & Assumptions (0) | 2023.08.30 |
[Spring] Junit이란? (0) | 2023.08.28 |