Junit5 : Junit Platform + Junit Jupiter + Junit Vintage 모듈로 구성

  1. Junit Platform : 테스트를 싱핼해주는 런쳐와 TestEngine API 제공
  2. Junit Jupiter : TestEngine API의 구현체로 Junit5의 새롭게 확장된 모델 제공
  3. Junit Vintage : 하위 호환성을 위하여 Junit4, Junit3를 실행할 수 있는 모듈 제공

spring-boot-starter-test에 포함되어 있다.

어노테이션

테스트

1. @Test : 단위테스트 메서드 명시

@Test
void test() {
    ...
}

2. @ParameterizedTest : 여러 매개변수를 대입해가며 테스트 실행

  • @ValueSource : value를 매개변수 설정
  • @EmptySource, @NullSource, @NullAndEmptySource : empty값, null값을 매개변수로 설정
  • @CsvSource : csv값을 매개변수로 설정
  • {displaName}, {index}, {arguments}, {0},{1},…(매개변후 번호)
@DisplayName("이름 출력 테스트")
@ParameterizedTest(name = "{index} {displayName} this={0}")
@ValueSource(strings = {"europani", "greeze"})
void nameTest(String name) {
    System.out.println(name);
}
  • 테스트 이름 : 1 이름 출력 테스트 this=europani
  • println : europani
@ParameterizedTest(name = "{index} {displayName} this={0}")
@ValueSource(ints = {10, 20})
void numTest(Integer num) {
    System.out.println(num);
}

3. @RepeatedTest : 반복적으로 테스트 실행

  • {displayName}, {currentRepetition}, {totalRepetitions} 를 사용하여 테스트 이름을 변경할 수 있다
  • RepetitionInfo 타입의 인자를 받을 수 있다
@DisplayName("리핏 테스트")
@RepeatedTest(value = 3, name = "{displayName}, {currentRepetition}/{totalRepetitions}")
void test(RepetitionInfo info) {
    System.out.println("test : " + info.getcurrentRepetitions() + "/" + info.getTotalRepetations());
}
  • 테스트 이름 : 리핏 테스트, 1/3
  • println : test : 1/3

4. @Disabled : 테스트 비활성화 [4버전 : @Ignore]

라이프사이클

  • @BeforeAll -> @BeforeEach -> @Test -> @AfterEach -> @AfterAll 사이클 순서
  1. @BeforeAll : 모든 테스트 전에 실행될 메서드 명시(테스트 클래스 수행시 1번만 실행) [4버전 : @BeforeClass]

  2. @AfterAll : 모든 테스트 후에 실행될 메서드 명시(테스트 클래스 종료시 1번만 실행) [4버전 : @AfterClassx]

  3. @BeforeEach : 각 단위테스트 전 마다 실행되는 메서드 [4버전 : @Before]

  4. @AfterEach : 각 단위테스트 후 마다 실행되는 메서드 [4버전 : @After]

조건

  1. @EnabledOnOs, @DisabledOnOs : 특정 OS에서 테스트 활성화/비활성화

  2. @EnabledOnJre, @DisabledOnJre : 특정 Java 버전에서 테스트 활성화/비활성화

  3. @EnabledIfEnvironmentVariable(name = "key", matches = "europani") : 환경변수 key의 값이 europani일 때 실행

기타

  1. @DisplayName : 테스트 이름 지정

  2. @Tag : 테스트 필터링을 위한 태그 선언

  3. @Timeout : 실행시간 제한 (실행시간을 초과하면 테스트 실패처리)

  4. @Order : 테스트 순서 지정

    • TestMethodOrder로 활성화
      • MethodOrderer.OrderAnnotation.class : @Order로 설정
      • MethodOrderer.Alphanumeric.class : 알파벳 순서
      • MethodOrderer.Random : 랜덤
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class appTest {

    @Order(1)
    void create_test() {}

    @Order(2)
    void read_test() {}
}
@Test
@Order(1)
void test_value() {
    ...
}

@Test
@Order(2)
void test_empty() {
    ...
}

assert 메서드 (org.junit.jupiter.api.Assertions.*)

assert 메서드 설명
assertArrayEquals(a, b) 배열 a와 b가 일치하는지 확인
assertEquals(a, b) 객체 a와 b가 같은 값인지 확인
assertSame(a, b) 객체 a와 b가 같은 객체인지 확인
assertTrue(a) 조건 a가 참인지 확인
assertNotNull(a) 객체 a가 not Null인지 확인
assertThrows(exception.class, 코드) 해당 코드 실행시 예상한 exception가 발생하는지 확인
fail() 테스트 실패처리

assertThat 관련 메서드 (org.assertj.core.api.Assertions.assertThat)

AssertJ

Spring-Test 어노테이션

  1. @ExtendWith(SpringRunner.class) : JUnit 테스트를 스프링 프레임워크와 통합 (테스트가 스프링 컨테이너에서 실행된다) [4버전 : @Runwith]

  2. @ContextConfiguration : 테스트시 사용할 설정파일 지정

  3. @SpringBootTest : Spring Boot를 사용하여 테스트를 진행한다 (일반적으로 통합테스트에 사용)

    • 테스트에 필요한 거의 모든 의존성을 제공 - @ExtendWith 의존성 포함
    • classes 파라미터를 사용하여 테스트에 필요한 Bean을 등록하지 않으면 모든 Bean이 사용된다.

    • 슬라이스 테스트 어노테이션
      • 모든 빈을 등록하는 @SpringBootTest와는 달리 필요한 빈만 등록할 수 있게 해준다
      • @DataJpaTest, @WebMvcTest, @JsonTest, @WebFluxTest

예외처리 테스트(assertThrows)

  • assertThrows(Class<T> expectedType, Executable executable) : 두번째 인자의 코드를 실행할 때 첫번째 인자의 익셉션이 발생하는지 테스트
@SpringBootTest
class ExceptionTest {

    @Autowired
    MemberService memberService;

    @Test
    @DisplayName("중복회원 가입 실패")
    public join() {
        // 1. Given
        Member member1 = new Member();
        member1.setName("spring");
        
        Member member2 = new Member();
        member2.setName("spring");

        // 2. When
        memberService.join(member1);
        // memberService.join()을 실행했을 때 IllegalStateException이 발생하는지
        IllegalStateException exception = assertThrows(IllegalStateException.class,
            () -> memberService.join(member2));

        // 3. Then
        assertEquals("이미 존재하는 회원입니다.", exception.getMessage());
    }

}