본문 바로가기
Java/Junit

[Spring] JUnit5 Assertions & Assumptions

by tableMinPark 2023. 8. 30.

Assertions란?

테스트의 결과 값을 검증하는 역할

 

Assertions는 테스트가 원하는 결과를 제대로 리턴하는지 또는 에러가 발생하진 않는지 검증하는 역할을 하는 메소드입니다.

JUnit4버전과 5버전 사이에 Assertions 차이점은 Java 8의 람다를 사용할 수 있다는 점입니다. 람다를 사용하여 테스트 코드를 작성하면 Functional하게 테스트 코드를 작성하는 것이 가능합니다.

 

Assertions 메소드

메소드명 설명
fail() 무조건 실패 (레거시에 사용하면 좋다.)
assertTrue(조건) 조건이 True이면 성공
assertFalse(조건) 조건이 False이면 성공
assertNull(A) A가 Null이면 성공
assertNotNull(A) A가 Null이 아니면 성공
assertEquals(A, B) A와 B가 동일하다면 성공
assertArrayEquals(A, B) A 배열과 B 배열이 동일하다면 성공
assertIterableEquals(A, B) A Iterable과 B Iterable이 동일하다면 성공
assertLinesMatch(A, B) A Stream과 B Stream이 동일하다면 성공
assertNotEquals(A, B) A와 B가 다르면 성공
assertSame(A, B) A Object가 B Object와 동일하다면 성공
assertNotSame(A, B) A Object와 B Object가 다르면 성공
assertAll 여러 Assertion이 True이면 성공
assertThrows 예상한 예외가 발생하면 성공
assertDoesNotThrow 예상한 예외가 발생하지 않으면 성공
assertTimeout 테스트가 지정된 시간보다 오래 걸리지 않으면 성공 (지정한 시간보다 오래 걸려도 테스트가 끝날 때까지 대기한다.)
assertTimeoutPreemptively 테스트가 지정된 시간보다 오래 걸리지 않으면 성공 (지정된 시간보다 오래 걸린 경우 바로 테스트를 종료한다.)

 

Assertions 예시

모든 메소드를 테스트하지 않고 사용 방법이 다른 3개의 메소드만 예시로 들었습니다.

1. 테스트 코드

public class AssertionsTest {
    private LocalDateTime start;
    @BeforeEach
    void setTime() {
        start = LocalDateTime.now();
    }
    @AfterEach
    void getSecond() {
        Duration duration = Duration.between(start, LocalDateTime.now());
        System.out.printf("소요 시간 : %d 초", duration.getSeconds());
    }

    @Test
    void assertAllTest() {
        assertAll("assertAll 테스트",
                () -> assertTrue(1 == 1),
                () -> assertTrue(2 == 2));
    }
    @Test
    void assertTimeoutTest() {
        LocalDateTime now = LocalDateTime.now();

        String actualResult = assertTimeout(Duration.ofSeconds(1), () -> {
            // 5초 간 중지
            Thread.sleep(5 * 1000);
            return "test";
        });

        assertEquals("test", actualResult);

    }
    @Test
    void assertTimeoutPreemptivelyTest() {

        String actualResult = assertTimeoutPreemptively(Duration.ofSeconds(1), () -> {
            // 5초 간 중지
            Thread.sleep(5 * 1000);
            return "test";
        });

        assertEquals("test", actualResult);
    }
}

 

2. assertAll

@Test
void assertAllTest() {
    assertAll("assertAll 테스트",
            () -> assertTrue(1 == 1),
            () -> assertTrue(2 == 2));
}

여러 개의 AssertTrue문이 하나의 assertAll문 안에서 동작되는 것을 확인할 수 있습니다.

 

3. assertTimeout

private LocalDateTime start;

@BeforeEach
void setTime() {
    start = LocalDateTime.now();
}
@AfterEach
void getSecond() {
    Duration duration = Duration.between(start, LocalDateTime.now());
    System.out.printf("소요 시간 : %d 초", duration.getSeconds());
}

@Test
void assertTimeoutTest() {
    LocalDateTime now = LocalDateTime.now();

    String actualResult = assertTimeout(Duration.ofSeconds(1), () -> {
        // 5초 간 중지
        Thread.sleep(5 * 1000);
        return "test";
    });

    assertEquals("test", actualResult);

}

assertTimeout은 타임 아웃 시간인 1초를 넘어서 5초를 채우고 종료되는 것을 확인할 수 있습니다.

 

4. assertTimeoutPreemptively

private LocalDateTime start;

@BeforeEach
void setTime() {
    start = LocalDateTime.now();
}
@AfterEach
void getSecond() {
    Duration duration = Duration.between(start, LocalDateTime.now());
    System.out.printf("소요 시간 : %d 초", duration.getSeconds());
}

@Test
void assertTimeoutPreemptivelyTest() {

    String actualResult = assertTimeoutPreemptively(Duration.ofSeconds(1), () -> {
        // 5초 간 중지
        Thread.sleep(5 * 1000);
        return "test";
    });

    assertEquals("test", actualResult);
}

assertTimeoutPreemptively는 assertTimeout과는 다르게 타임 아웃 시간인 1초가 되면 5초를 채우지 않고 바로 종료되는 것을 확인할 수 있습니다.


Assumptions란?

조건이 충족되면 실행되도록 하는 역할

 

Assumptions는 특정 상황에서만 test문을 실행하고자 할 때, 반대로 특정 상황에서만 실행하지 않고자할 때 사용하는 키워드입니다. 즉 테스트 메서드가 특정한 조건에 대해서 실행하고자 할 때 사용하는 구문입니다. 

 

Assumptions 메소드

메소드 설명
assumeTrue(조건) 조건이 False이면 테스트 중지
assumeFalse(조건) 조건이 True이면 테스트 중지
assumingThat(A, B) A 조건이 True이면 B 함수 실행 (A 조건이 False인 경우에도 테스트를 중지하지 않고 다음 코드를 진행한다.)

 

Assumptions 예시

1. 테스트 코드

public class AssumptionTest {
    private String env = "dev";

    @Test
    void assumeTrueTest() {
        assumeTrue(env.equals("dev"));
        System.out.println("test_1");

        assumeTrue(env.equals("local"));
        System.out.println("test_2");
    }

    @Test
    void assumeFalseTest() {
        assumeFalse(env.equals("local"));
        System.out.println("test_3");

        assumeFalse(env.equals("dev"));
        System.out.println("test_4");
    }

    @Test
    void assumeThatTest() {
        assumingThat(env.equals("local"), () -> {
            System.out.println("test_5");
        });

        assumingThat(env.equals("dev"), () -> {
            System.out.println("test_6");
        });
    }
}

 

2. assumeTrue

private String env = "dev";

@Test
void assumeTrueTest() {
    assumeTrue(env.equals("dev"));
    System.out.println("test_1");

    assumeTrue(env.equals("local"));
    System.out.println("test_2");
}

첫 번째 assumeTrue는 True이기 때문에 통과하고 "test_1"이 출력되지만, 두 번째 assumeTrue는 False이기 때문에 통과하지 못하고 테스트가 멈춘 것을 확인할 수 있습니다.

 

3. assumeFalse

private String env = "dev";

@Test
void assumeFalseTest() {
    assumeFalse(env.equals("local"));
    System.out.println("test_3");

    assumeFalse(env.equals("dev"));
    System.out.println("test_4");
}

첫 번째 assumeFalse는 False이기 때문에 통과하고 "test_3"이 출력되지만, 두 번째 assumeFalse는 True이기 때문에 통과하지 못하고 테스트가 멈춘 것을 확인할 수 있습니다.

 

4. assumeThat

private String env = "dev";

@Test
void assumeThatTest() {
    assumingThat(env.equals("local"), () -> {
        System.out.println("test_5");
    });

    assumingThat(env.equals("dev"), () -> {
        System.out.println("test_6");
    });
}

첫 번째 assumingThat은 False이기 때문에 "test_5"가 출력되지 않습니다. 조건이 맞지 않지만 테스트가 멈추지 않고 두 번째 assumingThat을 실행하고 "test_6"가 출력되는 것을 확인할 수 있습니다.


Assertions VS Assumptions

처음에 Assertions와 Assumptions를 정리하면서 도데체 무슨 차이가 있는거지? 라는 생각을 했습니다. 

하지만 직접 실행하고 확인해보니 이해를 할 수 있었습니다.

 

Assertions : 개발자가 테스트하고 싶은 값을 넣었을 때 결과 값이 예상한 값과 일치하는지 확인하는데 사용

ex) "A"를 넣으면 "B"가 나온다.

 

Assumptions : 개발자가 인자 값을 정확히 모를 때 조건문과 같은 용도로 사용

ex) 현재 개발자 환경이 "dev" 라면 테스트를 진행해라.