Assertj 를 사용한 테스트

알파로그·2024년 1월 29일
0

Test code

목록 보기
1/2

✏️ 발단

평소 테스트 코드르를 작성할 때 assertj 의 assertThat 을 주로 애용했는데 이번에 SoftAssertions 에 대해 알게되어 각각의 특징에 대해 알아보았다.

또 assertAll 과 AssertSoftly 의 차이점도 알아봤다.

✏️ assertThat

  • 가장 기본적인 Test 메서드로 한줄씩 검증을 이어나갈 수 있다.
@Test
void no1() {
    String nickname = "name";
    int age = 10;

    Member member = createMember(nickname, age);

    assertThat(member.getNickname()).isEqualTo(nickname);
    assertThat(member.getAge()).isEqualTo(age);
}
  • 위 방법은 가장 기본적인 방법이지만,
    하나의 객체의 필드를 각각 검증할 땐 가독성이 급격히 떨어지는 문제가 발생한다.
    - hasFieldOrPropertyWithValue 를 사용해 개선할 수 있다.
@Test
void no1() {
    String nickname = "name";
    int age = 10;

    Member member = createMember(nickname, age);

    assertThat(member)
            .hasFieldOrPropertyWithValue("nickname", "nickname")
            .hasFieldOrPropertyWithValue("age", 30);
}

📍 문제점

  • assertThat 은 순차적으로 검증하고, 예상값과 다르면 로직을 바로 종료시킨다.
    • 즉, 이후의 검증은 확인되지 않게된다.
@Test
void no1() {
    String nickname = "name";
    int age = 10;
    boolean useAgreement = true;

    Member member = createMember(nickname, age, useAgreement);

    assertThat(member)
            .hasFieldOrPropertyWithValue("nickname", "nickname")
            .hasFieldOrPropertyWithValue("age", 30)
            .hasFieldOrPropertyWithValue("useAgreement", false);
}
  • 위 코드는 첫번째, 세번째에서 검증을 실패해야하지만,
    첫번째 밖에 찾아내지 못한다.
java.lang.AssertionError: 

Expecting
to have a property or a field named "nickname" with value
  "nickname"

but value was:
  "name"

(static and synthetic fields are ignored)

✏️ SoftAssertions

  • 검증해야 할 것이 많다면 SoftAssertions 를 사용하는 것이 좋다.
    • Test 가 실패하더라도 뒤에 남은 모든 검증을 마치고 한번에 잘못된 부분을 전부 체크해준다.
@Test
void no1() {
    String nickname = "name";
    int age = 10;
    boolean useAgreement = true;

    Member member = createMember(nickname, age, useAgreement);

    assertSoftly(softly -> {
        softly.assertThat(member.getNickname()).isEqualTo(nickname);
        softly.assertThat(member.getAge()).isEqualTo(age);
        softly.assertThat(member.getUseAgreement()).isEqualTo(useAgreement);
    });
}
  • assertSoftly 를 사용하면 아까와 같이 검증 실패가 곳곳에 있어도 한번에 전부 체크할 수 있다.
@Test
void no1() {
    String nickname = "name";
    int age = 10;
    boolean useAgreement = true;

    Member member = createMember(nickname, age, useAgreement);

    assertSoftly(softly -> {
        softly.assertThat(member.getNickname()).isEqualTo("nickname");
        softly.assertThat(member.getAge()).isEqualTo(age);
        softly.assertThat(member.getUseAgreement()).isEqualTo(false);
    });
}
org.assertj.core.error.AssertJMultipleFailuresError: 

Multiple Failures (2 failures)

-- failure 1 --
expected: "nickname"
 but was: "name"

at ... .java:20)

-- failure 2 --
expected: false
 but was: true

at ... .java:22)
  • 가독성을 높히기 위해 hasFieldOrPropertyWithValue 를 사용해도 잘 작동된다
@Test
void no1() {
    String nickname = "name";
    int age = 10;
    boolean useAgreement = true;

    Member member = createMember(nickname, age, useAgreement);

    assertSoftly(softly -> {
        softly.assertThat(member)
                .hasFieldOrPropertyWithValue("nickname", "nickname")
                .hasFieldOrPropertyWithValue("age", age)
                .hasFieldOrPropertyWithValue("useAgreement", false);
    });
}
org.assertj.core.error.AssertJMultipleFailuresError:
 
Multiple Failures (2 failures)

-- failure 1 --
Expecting
to have a property or a field named "nickname" with value
  "nickname"

but value was:
  "name"

(static and synthetic fields are ignored)
at ... .java:21)

-- failure 2 --
Expecting
to have a property or a field named "useAgreement" with value
  false

but value was:
  true

(static and synthetic fields are ignored)
at ... .java:23)

✏️ assertAll VS. AssertSoftly

  • 두가지 모두 검증이 실패해도 끝까지 메서드를 완료해 실패한 모든 부분을 체크해 제공하지만 차이점이 있다.

📍 차이점

  1. assertAll 은 Junit 의 라이브러리고, AssertSoftly 는 Junit 의 Assertions 를 보완하고 확장한 라이브러리인 AssertJ 이다.
  2. assertAll 은 검증이 실패한 코드의 라인 위치를 표시해주지 않는다.
    • 기대값과 실제값만 보여줌

📍 나의 생각

  • 단일일 경우 assertThat 을 사용
  • 여러개일 경우 AssertSoftly 를 사용
    • 한 객체의 여러 필드를 검증 할 경우 hasFieldOrPropertyWithValue 를 사용
profile
잘못된 내용 PR 환영

0개의 댓글