본문 바로가기
Test

AssertJ 기본 사용법

by byeongoo 2021. 11. 15.

1. AssertJ란?

AssertJ란 asssertion(직역 : 주장)을 제공하는 자바 라이브러리로 에러 메세지와 테스트 코드의 가독성을 높여주는 라이브러리이다.

 

junit5에서 제공하는 Assertions의 assert는 인자 순서 (expected, actual)의 순서가 헷갈릴 수 있는데 Assertions보다 가독성이 좋아진다.

assertEquals(expected, actual); 
assertThat(actual).isEqualTo(expected);

 

  • 메소드 체이닝을 지원하기 때문에 좀 더 깔끔하고 읽기 쉬운 테스트 코드를 작성할 수 있다.
  • 개발자가 테스트를 하면서 필요한 거의 모든 메소드를 제공한다.

 

2. 의존성 추가

//maven
<dependency>
    <groupId>org.assertj</groupId>
    <artifactId>assertj-core</artifactId>
    <version>3.21.0</version>
    <scope>test</scope>
</dependency>

//gradle
testImplementation group: 'org.assertj', name: 'assertj-core', version: '3.21.0'

 

3. 메소드 임폴트

import static org.assertj.core.api.Assertions.*;

 

4. 테스트 대상 지정

assertThat(테스트 타켓).메소드1().메소드2().메소드3();

 

5. 문자열 테스트 예시

@Test
@DisplayName("테스트 코드 작성")
public void numTest() {
    assertThat("Hello, world! Nice to meet you.") // 주어진 "Hello, world! Nice to meet you."라는 문자열은
            .isNotEmpty() // 비어있지 않고
            .contains("Nice") // "Nice"를 포함하고
            .contains("world") // "world"도 포함하고
            .doesNotContain("ZZZ") // "ZZZ"는 포함하지 않으며
            .startsWith("Hell") // "Hell"로 시작하고
            .endsWith("u.") // "u."로 끝나며
            .isEqualTo("Hello, world! Nice to meet you."); // "Hello, world! Nice to meet you."과 일치합니다.
}

6. 숫자 테스트 예시

@Test
@DisplayName("숫자 테스트")
public void test() {
    assertThat(3.14d) // 주어진 3.14라는 숫자는
            .isPositive() // 양수이고
            .isGreaterThan(3) // 3보다 크며
            .isLessThan(4) // 4보다 작습니다
            .isEqualTo(3, offset(1d)) // 오프셋 1 기준으로 3과 같고
            .isEqualTo(3.1, offset(0.1d)) // 오프셋 0.1 기준으로 3.1과 같으며
            .isEqualTo(3.14); // 오프셋 없이는 3.14와 같습니다
}

7. description (에러 메세지)

  • 에러 메세지의 경우 as라는 메서드로 지정할 수 있다.
  • 단, as 메서드는 assertions이 수행되기전에 사용해야한다.
package assertj;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.List;

import static org.assertj.core.api.Assertions.*;

public class FailMessageTest {

    class Member {
        private String name;
        private int age;

        public Member(String name, int age) {
            this.name = name;
            this.age = age;
        }

        public String getName() {
            return name;
        }

        public int getAge() {
            return age;
        }

    }

    @Test
    @DisplayName("에러 메세지 출력")
    public void test() {
        Member frodo = new Member("Frodo", 33);
        frodo.getAge();
        // failing assertion, remember to call as() before the assertion, not after !
        assertThat(frodo.getAge())
                .as("check %s's age", frodo.getName())  // as를 assertion 이전에 넣는다.
                .isEqualTo(100);
    }
}

메세지 결과 

[check Frodo's age] expected:<100> but was:<33>

8. filtering assertions - iterables or array에 적용

@Test
@DisplayName("람다식을 이용한 필터링")
public void filterTest() {
    //given
    List<Member> list = new ArrayList<>();
    Member kim = new Member("Kim", 22);
    Member park = new Member("Park", 25);
    Member lee = new Member("Lee", 22);
    Member amy = new Member("Amy", 25);
    Member jack = new Member("Jack", 22);

    list.add(kim); list.add(park);
    list.add(lee); list.add(amy);
    list.add(jack);

    // when && then
    assertThat(list).filteredOn(human -> human.getName().contains("a"))
            .containsOnly(park, jack);
}

9. extracting

  • 리스트에서 특정 필드만 뽑아서 테스트 가능
@Test
@DisplayName("특정 속성 추출 테스트")
public void extractTest() {
    //given
    List<Member> list = new ArrayList<>();
    Member kim = new Member("Kim", 22);
    Member park = new Member("Park", 25);
    Member lee = new Member("Lee", 22);
    Member amy = new Member("Amy", 25);
    Member jack = new Member("Jack", 22);

    list.add(kim);
    list.add(park);
    list.add(lee);
    list.add(amy);
    list.add(jack);

    // then
    assertThat(list).extracting("name")
            .contains("Kim", "Park", "Lee", "Amy", "Jack");
}
  • 여러 필드를 검사하고 싶을 경우 tuple 사용
@Test
@DisplayName("특정 속성 추출 테스트2")
public void extractTest2() {
    //given
    List<Member> list = new ArrayList<>();
    Member kim = new Member("Kim", 22);
    Member park = new Member("Park", 25);
    Member lee = new Member("Lee", 22);
    Member amy = new Member("Amy", 25);
    Member jack = new Member("Jack", 22);

    list.add(kim);
    list.add(park);
    list.add(lee);
    list.add(amy);
    list.add(jack);

    // then
    assertThat(list).extracting("name", "age")
            .contains(tuple("Kim", 22),
                    tuple("Park", 25),
                    tuple("Lee", 22),
                    tuple("Amy", 25),
                    tuple("Jack",22));
}

10. Soft assertions

  • Soft assertions를 사용하면 모든 assertions을 실행한 후 실패 내역만 확인 가능
@Test
@DisplayName("soft assertions로 한번에 검증")
public void softAssertionsTest() {
    int num1 = 3;
    int num2 = 5;
    String str = "hello";

    SoftAssertions softly = new SoftAssertions();
    softly.assertThat(num1).as("num1 is %d", num1).isEqualTo(5);
    softly.assertThat(num2).as("num2 is %d", num2).isEqualTo(6);
    softly.assertThat(str).as("str is %s", str).isEqualTo("hi");
    softly.assertAll();
}

11. Exception 처리 테스트

  • assertThatThrownBy() 메서드를 통해서 예외 처리를 할 수 있다.
@Test
public void exceptionAssertionTest1() {
    // WHEN
    Throwable thrown = catchThrowable(() -> { throw new Exception("boom!"); });

    // THEN
    assertThat(thrown).isInstanceOf(Exception.class)
            .hasMessageContaining("boom");
}
@Test
public void exceptionAssertionTest2() {
    assertThatThrownBy(() -> { throw new Exception("boom!"); })
            .isInstanceOf(Exception.class)
            .hasMessageContaining("boom");
}

 

12. 자주 쓰이는 예외 처리 systax

 

  • assertThatNullPointerException
  • assertThatIllegalArgumentException
  • assertThatIllegalStateException
  • assertThatIOException
@Test
public void exceptionAssertionTest3() {
    assertThatIOException().isThrownBy(() -> { throw new IOException("boom!"); })
            .withMessage("%s!", "boom")
            .withMessageContaining("boom")
            .withNoCause();
}​

 

REFERENCE

https://pjh3749.tistory.com/241

 

[AssertJ] JUnit과 같이 쓰기 좋은 AssertJ 필수 부분 정리

AssertJ가 core document를 새로운 github.io로 이전했네요 :) . 본 글은 AssertJ 공식 문서를 핵심 챕터를 선정하여 번역하며 정리한 글 입니다. http://joel-costigliola.github.io/assertj/assertj-core.html A..

pjh3749.tistory.com

https://steady-coding.tistory.com/351

 

AssertJ 필수 기능 정리 (JAVA)

안녕하세요? 코딩중독입니다. JUnit가 같이 쓰기 좋은 AssertJ의 필수 기능들에 대해 소개하려고 합니다. 공식 문서는 이곳에서 참고하실 수 있으며, 틀리거나 미흡한 부분은 지적해 주시면 감사하

steady-coding.tistory.com