JUnit5 사용하여 테스트 코드 작성하기 본문

백앤드 개발일지/스프링부트

JUnit5 사용하여 테스트 코드 작성하기

giron 2021. 9. 30. 20:09
728x90

테스트코드를 작성해보면서 JUnit4나 5를 사용하는데 이번 포스팅에서 4와 5를 비교하고 JUnit5 사용법에 초점을 맞춰서 정리해두려고한다.

Junit5

  • Platform: Junit으로 작성한 테스트를 실행해주는 런처를 제공한다. TestEngineApi 제공한다.
  • Vintage: Junit3과 4를 지원하는 TestEngine 구현체
  • Jupiter: Junit5를 지원하는 TestEngineApI 구현체

Junit 5는 스프링부트 2.2 버전 이상부터는 기본적으로 의존성이 장착되어 따로 설정할 필요가 없다.

Junit5의 애노테이션들

@Test

 - 테스트 메서드를 나타내주는 애노테이션이다.

 - Junit4와 달리 어떠한 속성도 선언하지 않는다.

//Junit4
@Test(expected = Exception.class)
void test() throws Exception{
	...
}

//Junit5
@Test
void test(){
	...	
}

@BeforeAll

 - 해당 클래스에 위치한 모든 테스트 메서드 실행 전에 딱 한 번만 실행되는 메서드를 표시

 - 해당 메서드는 static으로 선언해야한다.

@AfterAll

 - 해당 클래스에 위치한 모든 테스트 메서드 실행 후에 딱 한 번만 실행되는 메서드를 표시

 - 해당 메서드는 static으로 선언해야한다.

@BeforeEach

- 해당 클래스에 위치한 모든 테스트 메서드 실행 전에 실행되는 메서드를 표시

@AfterEach

- 해당 클래스에 위치한 모든 테스트 메서드 실행 후에 실행되는 메서드를 표시

 

각각 Junit4에 @BeforeClass/@AfterClass/@Before/@After와 유사하다.

BeforeAll vs BeforeEach

둘의 차이를 이해하기 힘들었는데 코드를 보면 이해하기 쉬울것 같다.

public class Test {

    @BeforeAll
    public static void beforeAll() {
        System.out.println("@BeforeAll");
    }

    @BeforeEach
    public void beforeEach() {
        System.out.println("@BeforeEach");
    }

    @Test
    public void test1(){
        System.out.println("@Test 1");
    }

    @Test
    public void test2(){
        System.out.println("@Test 2");
    }

    @AfterEach
    public void afterEach() {
        System.out.println("@AfterEach");
    }

    @AfterAll
    public static void afterAll() {
        System.out.println("@AfterAll");
    }
}

[결과]

@BeforeAll

@BeforeEach
@Test 1
@AfterEach

@BeforeEach
@Test 2
@AfterEach

@AfterAll

따라서, 테스트가 조건들에 의해 변경이 없다면 @BeforeAll, 변경이 있을 수도 있다면  @BeforeEach를 사용하면 좋다고 한다!

 

@Disabled

 - 테스트 클래스나 테스트 메소드 를 사용하지 않는데 사용된다.
 - Junit 4의 @Ignore 와 비슷하다.

[실행]

[결과]

 

@DisplayName

 - 어떤 테스트인지 표시해주는 애노테이션

 - 공백, 이모지, 특수문자까지 전부 지원해준다.

 

@RepeatedTest

 - 특정 테스트를 반복 시키고 싶을때 사용하는 애노테이션

 - 반복 횟수와 반복 테스트 이름을 설정 가능하다.

 - 성능테스트를 할때 유용하다.

public class JunitTest {
    @RepeatedTest(10)
    @DisplayName("반복 테스트")
    void repeatedTest() {

    }

    @RepeatedTest(value = 10, name = "{displayName} 중 {currentRepetition}")
    @DisplayName("반복 테스트2")
    void repeatedTest2(){

    }
}

@ParameterizedTest

 - 테스트에 여러 다른 매개변수들을 대입해가며 반복 실행할 때 사용하는 애노테이션

public class JunitTest {
    
    @ParameterizedTest
    @CsvSource(value = {"ACE, ACE:12", "ACE, ACE, ACE:13", "ACE,ACE,TEN:12"}, delimiter = ':')
    void 에이스_카드가_여러_개일때_합_구하기(final String input, final int expected) {
        final String[] inputs = input.split(",");
        
        for(final String number : inputs){
            final CardNumber cardNumber = CardNumber.valueOf(number);
            dealer.receiveOneCard(new Card(cardNumber, CardType.CLOVER));
        }
        assertThat(dealer.calculateScore()).isEqualTo(expected);
    }

}

delimiter를 기준으로 input과 expected로 값이 들어간다.

 

@Nested

- 테스트 클래스 안에서 내부 클래스를 정의해 테스트를 계층화 할 때 사용한다.

 - @BeforeEach, @AfterEach와 같은 테스트 생명주기에 관계된 메서드들도 계층에 맞춰 동작한다.

 

@Assertions

  • assertAll
    • 매개변수로 받는 모든 테스트코드를 한번에 실행
    • 오류가 나도 끝까지 실행한 뒤 한 번에 모아서 출력
    • public class JunitTest {
      
          @Test
          public void createProduct(){
              Product product = new Product();
              assertAll(
                      () -> assertNotNull(product),
                      () -> assertEquals(product.getMyprice(), 5000),
                      () -> assertTrue(product.getLprice() < 1000, "1000원보다는 비싸야 한다.")
              );
          }
      
      }


    • 2번째에서 에러가 발생했지만 마지막은 통과됨
  • assertThrows(expectedType, executable)
    • 예외 발생을 확인하는 테스트
    • executable의 로직이 실행하는 도중 expectedType의 에러를 발생시키는지 확인 
    • public class JunitTest {
      
          @Test
          public void createProduct(){
              Product product = new Product();
              Exception e = assertThrows(Exception.class, () -> new Product(-100));
              //예외가 던져지지 않음을 확인하는 assertDoesNotThrow
              assertDoesNotThrow(()-> System.out.println("do it"));
          }
      
      }
  • assertTimeout(duration, executable)
    • 특정 시간 안에 실행이 완료되는지 확인
    • duration: 원하는 시간
    • executable: 테스트할 로직
    • public class JunitTest {
      
          @Test
          @DisplayName("타임아웃 준수")
          void timeOutNotExceed(){
              assertTimeout(ofMinutes(2), ()->Thread.sleep(10));
          }
          @Test
          @DisplayName("타임아웃 초과")
          public void timeOut(){
              assertTimeout(ofMillis(10), () -> Thread.sleep(100));
          }
      
      }

레거시 Junt4 -> Junit5 변환

수작업으로 옮기는줄 알았는데 클릭으로만 가능한 방법이 있었다..!

이 외에 많은 기능들이 있었지만 자주 사용할법한 기능들을 위주로 정리했다.

테스트할때마다 자주 확인해야겠다.

 

Reference

 

[JUnit] JUnit5 사용법 - 기본 - Heee's Development Blog

Step by step goes a long way.

gmlwjd9405.github.io

 

[JUnit] JUnit5 사용법 - 기본 - Heee's Development Blog

Step by step goes a long way.

gmlwjd9405.github.io

  • https://www.youtube.com/watch?v=EwI3E9Natcw&t=1s : 우아한Tech - 10분 테코톡
728x90
Comments