AssertJ

AssertJ는 테스트 라이브러리이다.

  • 메소드 체이닝을 지원하기 때문에 좀 더 깔끔하고 읽기 쉬운 테스트 코드 작성 가능(가독성이 좋음)

  • 개발자가 테스트를 하면서 필요하다고 상상할 수 있는 거의 모든 메소드를 제공

의존성

spring-boot-starter-test에 기본적으로 포함되어있다. spring-boot-starter-test를 사용하지 않고 추가하는 경우에는 다음과 같이 추가할 수 있다.

Gradle

testCompile 'org.assertj:assertj-core:3.21.0'

Maven

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

테스트 코드 작성 시작하기

Assertions.assertThat()

모든 테스트 코드는 assertThat() 메서드에서 시작한다.

assertThat(테스트 타겟)
    .method1()
    .method2()
    .method3();

테스트 실패 메세지

  • 테스트 실패시 나타낼 메세지를 .as()로 표현할 수 있다.

  • 반드시 검증 문 앞에 작성되어야한다.

    @Test
    void asExample() {
        String blank = " ";
        assertThat(StringUtils.hasText(blank))
                .as("check '%s' is null", blank)
                .isTrue();
    }

다음과 같이 작성해두면 테스트 실패시 콘솔창에 에러메세지가 다음과 같이 출력된다.

[check ' ' is null] 
Expecting value to be true but was false
org.opentest4j.AssertionFailedError: [check ' ' is null] 

다음과 같이 검증문 뒤에 작성할 경우 호출되지 않는 것을 볼 수 있다.

    @Test
    void asExample() {
        String blank = " ";
        assertThat(StringUtils.hasText(blank))
                .isTrue()
                .as("check '%s' is null", blank);
    }
Expecting value to be true but was false
org.opentest4j.AssertionFailedError: 
Expecting value to be true but was false

Collection 필터링

.filteredOn()

.filteredOn()으로 테스트할 데이터들을 필터링 할 수 있다.

    @Test
    void test() {
        EnumSet<DayOfWeek> days = EnumSet.allOf(DayOfWeek.class);
        assertThat(days)
                .filteredOn(d -> d.getValue() > 4)
                .containsOnly(DayOfWeek.FRIDAY, DayOfWeek.SATURDAY, DayOfWeek.SUNDAY);
    }

이때 not, in, notIn에 대한 객체 프로퍼티를 검증할 수 도 있다.

        List<Human> list = new ArrayList<>();
        list.add(new Human("faker", 26));
        list.add(new Human("bang", 26));
        list.add(new Human("wolf", 26));
        list.add(new Human("keria", 20));

        assertThat(list)
                .filteredOn("age", not(26))
                .containsOnly(list.get(3));

Collection Data Extracting

기존의 클래스의 특정 데이터를 비교하기 위해서는 별도 리스트를 만들어 다음과 같이 테스트를 진행해야했다.

@Test
void no_extracting() throws Exception{
    List<String> names = new ArrayList<>();
    for (T1 member : members) {
        names.add(member.getName());
    }

    assertThat(names).containsOnly("faker", "bang", "wolf", "keria");
}

하지만 assertj에서 extracting을 지원해주면서 필요한 데이터만 추출해 테스트가 가능해졌다.

    @Test
    void extracting() {
        List<T1> members = new ArrayList<>();
        members.add(new T1("faker", 26));
        members.add(new T1("bang", 26));
        members.add(new T1("wolf", 26));
        members.add(new T1("keria", 20));

        assertThat(members)
                .extracting("name")
                .contains("faker", "bang", "wolf", "keria");


        assertThat(members)
                .extracting("name", "age")
                .contains(tuple("faker", 26),
                        tuple("bang", 26),
                        tuple("wolf", 26),
                        tuple("keria", 20));
    }

추출할 데이터가 한개라면 타입 지정이 가능하며, 여러개인 경우에는 assertj에서 지원해주는 tuple()로 테스트할 수 있다.

SoftAssertions

Assertions.assertThat()은 테스트가 한개라도 실패하면 해당 테스트는 중지된다.

SoftAssertions을 이용하면 모든 assertThat을 실행하고 해당 실패 내역을 확인할 수 있다.

    @Test
    void test() {
        String str = "test";
        SoftAssertions.assertSoftly(softAssertions -> {
            softAssertions.assertThat(StringUtils.hasText(str))
                    .as("check '%s' is not null", str)
                    .isFalse();

            softAssertions.assertThat(StringUtils.hasLength(str))
                    .as("check '%s' is not null", str)
                    .isTrue();
        });
    }
Multiple Failures (1 failure)
-- failure 1 --
[check 'test' is not null] 
Expecting value to be false but was true
at SoftAssertionTest.lambda$test$0(SoftAssertionTest.java:15)
org.assertj.core.error.AssertJMultipleFailuresError: 
Multiple Failures (1 failure)
-- failure 1 --

참고

Last updated