본문 바로가기
Spring

[Spring] JUnit5 사용하기

by jaee_ 2021. 12. 5.

인프런 학습을 하다보니 강의와 동일하게 설정을 해도 테스트 시 지원되지 않는 코드들이 꽤 존재했습니다. 이유를 살펴보니 인프런 강의는 JUnit4를 사용하고, 저는 JUnit5로 의존성을 추가했기 때문에 지원되는 메소드 및 어노테이션이 달랐습니다. 오늘은 JUnit5의 특징과 JUnit4와 다른점은 무엇인지 간략히 알아보겠습니다. 

 

1. JUnit5 의 특징

이전 버전의 JUnit과는 달리 JUnit5는 세가지의 모듈로 구성됩니다. 

JUnit5 = JUnit Platform + JUnit Jupiter + JUnit Vintage

JUnit Platform : JVM에서 실행되는 테스트 프레임워크로 테스트 프레임워크를 개발하기 위한 TestEngine API를 정의합니다. 

 

JUnit Jupiter : JUnit5의 쓰기 테스트와 확장을 위한 새로운 프로그래밍 모델과 확장 모델의 조합으로 테스트를 실행할 수 있는 TestEngine 을 제공합니다. 

 

JUnit Vintage : JUnit 3 및 JUnit 4 기반 테스트를 실행하기 위한 TestEngine을 제공합니다. (클래스 경로 또는 모듈 경로에 JUnit 4.12 이상이 있어야 합니다.)

 

2. JUnit5 의 Annotations

Annotations 설명
@Test 테스트임을 나타내는 어노테이션입니다. 
@BeforeEach JUnit4의 @Before 어노테이션과 유사하며, 해당 주석이 달린 메소드가 @Test, @RepeatedTest, @ParameterizedTest @TestFactory 이전에 실행되어야 함을 알리는 어노테이션입니다. 
@AfterEach JUnit4의 @After 어노테이션과 유사하며, 해당 주석이 달린 메소드가 @Test, @RepeatedTest, @ParameterizedTest, @TestFactory 이후에 실행되어야 함을 알리는 어노테이션입니다. 
@BeforeAll JUnit4의 @BeforeClass 어노테이션과 유사하며 해당 주석이 달린 메소드가 @Test, @RepeatedTest, @ParameterizedTest, @TestFactory 이전에 실행되어야 함을 알리는 어노테이션입니다. 
@AfterAll JUnit4의 @AfterClass어노테이션과 유사하며 해당 주석이 달린 메소드가 @Test, @RepeatedTest, @ParameterizedTest, @TestFactory 이후에 실행되어야 함을 알리는 어노테이션입니다. 
@Disabled 테스트 클래스 또는 테스트 메서드를 비활성화하는 데 사용되며, JUnit 4의 @Ignore 어노테이션과 유사합니다.
@ExtendWith 확장을 선언적으로 등록하는 데 사용됩니다. 스프링을 사용하려면 @ExtendWith(SpringExtension.class)를 선언하여 사용합니다. 
@DisplayName 테스트 클래스 또는 테스트 메서드의 사용자가 지정할 이름을 선언합니다.
@TestMethodOrder 주석이 달린 테스트 클래스에 대한 테스트 방법 실행 순서를 구성하는 데 사용되며, JUnit 4의 @FixMethodOrder와 유사합니다.

 

이 외의 어노테이션에 대한 정보가 궁금하다면 JUnit User Guide 를 통해 확인하실 수 있습니다. 

 

3. JUnit5 의 특징 예제로 살펴보기

공식문서를 보다가 이전에도 (JUnit4) 존재했는지는 모르겠지만, 개인적으로 호기심이 갔던 기능들이 있어서 예제코드와 함께 적어보려 합니다. 

운영 체제 조건

@EnabledOnOs 또는 @DisabledOnOs 어노테이션을 통해 특정 운영 체제에서 활성화되거나 비활성화할 수 있습니다.

package com.infren.study.demowebmvc;

import static org.junit.jupiter.api.condition.OS.LINUX;
import static org.junit.jupiter.api.condition.OS.MAC;
import static org.junit.jupiter.api.condition.OS.WINDOWS;

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.Test;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.EnabledOnOs;

public class JunitTest {

    @Test
    @EnabledOnOs(MAC)
    void onlyOnMacOs() {
        System.out.println("MAC");
    }

    @TestOnMac
    void testOnMac() {
        System.out.println("testOnMac");
    }

    @Test
    @EnabledOnOs({ LINUX, MAC , WINDOWS})
    void onLinuxOrMacOrWindow () {
        System.out.println("LINUX, MAC, WINDOWS");
    }

    @Test
    @DisabledOnOs(WINDOWS)
    void notOnWindows() {
        System.out.println("WINDOWS");
    }

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Test
    @EnabledOnOs(MAC)
    @interface TestOnMac {
    }
}

제 노트북의 운영체제는 Window 입니다. 위의 코드에서는 WINDOW 운영체제가 작동하는 테스트 메소드는 onLinuxOrMacOrWindow() 메소드 뿐입니다. 따라서 위의 결과처럼 onLinuxOrMacOrWindow() 메소드만 실행된 것을 볼 수 있습니다.

 

TMI이긴 하지만, 위 코드를 보면 @TestOnMac 이라는 어노테이션이 존재합니다. 궁금하여 @TestOnLinux, @TestOnWindow 를 쳐봤는데 그런 어노테이션은 존재하지 않더라구요 ㅎㅎ 윈도우 유저는 웁니다.. 언젠간 맥북을 사겠다는 다짐을 또 다시 합니다. (이유만들기) 

 

자바 런타임 환경 조건

@EnabledOnJre 또는 @DisabledOnJre 주석을 통해 특정 버전의 Java Runtime Environment(JRE) 또는 @EnabledForJReange 및 @DisabledForJReange 주석을 통해 특정 버전의 JRE에서 활성화 또는 비활성화할 수 있습니다.

이는 이전 버전(JUnit4) 에서도 존재하는 어노테이션입니다. 

 

package com.infren.study.demowebmvc;

import static org.junit.jupiter.api.condition.JRE.JAVA_10;
import static org.junit.jupiter.api.condition.JRE.JAVA_11;
import static org.junit.jupiter.api.condition.JRE.JAVA_8;
import static org.junit.jupiter.api.condition.JRE.JAVA_9;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledForJreRange;
import org.junit.jupiter.api.condition.DisabledOnJre;
import org.junit.jupiter.api.condition.EnabledForJreRange;
import org.junit.jupiter.api.condition.EnabledOnJre;

public class JUnitJreTest {
    @Test
    @EnabledOnJre(JAVA_8)
    void onlyOnJava8() {
        System.out.println("onlyOnJava8");
    }

    @Test
    @EnabledOnJre({ JAVA_9, JAVA_10 })
    void onJava9Or10() {
        System.out.println("onJava9Or10");
    }

    @Test
    @EnabledForJreRange(min = JAVA_9, max = JAVA_11)
    void fromJava9to11() {
        System.out.println("fromJava9to11");
    }

    @Test
    @EnabledForJreRange(min = JAVA_9)
    void fromJava9toCurrentJavaFeatureNumber() {
        System.out.println("fromJava9toCurrentJavaFeatureNumber");
    }

    @Test
    @EnabledForJreRange(max = JAVA_11)
    void fromJava8To11() {
        System.out.println("fromJava8To11");
    }

    @Test
    @DisabledOnJre(JAVA_9)
    void notOnJava9() {
        System.out.println("notOnJava9");
    }

    @Test
    @DisabledForJreRange(min = JAVA_9, max = JAVA_11)
    void notFromJava9to11() {
        System.out.println("notFromJava9to11");
    }

    @Test
    @DisabledForJreRange(min = JAVA_9)
    void notFromJava9toCurrentJavaFeatureNumber() {
        System.out.println("notFromJava9toCurrentJavaFeatureNumber");
    }

    @Test
    @DisabledForJreRange(max = JAVA_11)
    void notFromJava8to11() {
        System.out.println("notFromJava8to11");
    }
}

제가 실행한 환경은 Java 11 입니다. 그러므로 Java11버전 또는 11버전이 포함된 테스트 메소드가 통과한 것을 볼 수 있습니다.

 

개인적으로 관심이 갔던 2가지만 작성하니 추가적으로 궁금한 점이 있으시다면 JUnit User Guide를 통해 확인이 가능하십니다. 

 

4. JUnit4 -> JUnit5 마이그레이션

 

  • @Before, @After 가 사라지고, @BeforeEach@AfterEach로 변경되었습니다. 
  • @BeforeClass, @AfterClass가 사라지고, @BeforeAll@AfterAll로 변경되었습니다. 
  • @Ignore 는 더이상 존재하지 않습니다. @Disabled 또는 다른 기본 제공 실행 조건 중 하나를 사용하세요.
  • @Category가 사라지고, @Tag로 변경되었습니다.
  • @RunWith이 사라지고 @ExtendWith으로 변경되었습니다.
  • @Rule@ClassRule이 사라지고 @ExtendWith@Register로 변경되었습니다. 

 Junit5에서는 Assertion 의 위치가 org.junit.jupiter.api.Assertions으로 변경되었습니다. AssertJ, Hamcrest, Trust에서 제공하는 org.junit.Assert는 그대로 사용할 수 있습니다.

 

결정적으로 JUnit5를 찾아보게 된 이유가 @RunWith이었습니다. @ExtendWith으로 변경된 것을 알았으니 이제 헤매지 않을 것 같습니다. 


참고한 사이트

https://junit.org/junit5/docs/current/user-guide/#migrating-from-junit4

댓글