AssertJ로 테스트 코드를 작성해보자

하리보·2024년 12월 7일

AssertJ로 테스트 코드 작성해보자


1. AssertJ란 무엇인가?

테스트는 소프트웨어 개발의 중요한 과정 중 하나로, 코드의 품질을 보장하기 위해 정확하고 직관적인 검증이 필요합니다.

AssertJ는 자바 테스트에서 널리 사용되는 Assertion 라이브러리로, JUnit이나 TestNG와 함께 사용됩니다.
기존 assertEqualsassertTrue 같은 단순한 검증 메서드보다 가독성유연성이 뛰어나며, 다양한 데이터 타입과 객체를 검증할 수 있도록 풍부한 API를 제공합니다.

import

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

static 임포트를 하면 테스트 시 편리하다.


2. 왜 AssertJ를 사용해야 하는가?

(1) 코드 가독성

가장 많이 쓰는 equal 비교 테스트의 경우, a = b 인지 알아보기 위해서 기존 코드 방식으로 assertEquals(a, b)를 사용하는 것보다, assertThat(a).isEqualTo(b)로 쓰는 것이 실문장에 가까워 가독성이 높고, 더 직관적인 코드가 될 수 있습니다.

기존 코드 (JUnit 방식):

@Test
void testStringWithJUnit() {
    String actual = "abc";
    assertEquals("abc", actual);
}

AssertJ 코드:

@Test
void testStringWithAssertJ() {
    String actual = "abc";
    assertThat(actual).isEqualTo("abc");
}

비교:

  • 가독성: assertThat(actual).isEqualTo("abc")는 메서드 체이닝으로 더 읽기 쉽게 작성할 수 있습니다.
  • 직관성: 각 검증 조건이 독립적이고 자연어에 가까워 직관적으로 이해하기 쉽습니다.
  • 실패 메시지: AssertJ는 실패 시 더 구체적이고 유용한 메시지를 제공합니다.

(2) 구체적인 실패 메시지

AssertJ는 실패 메시지가 더 구체적이고 이해하기 쉽게 제공됩니다. 이는 디버깅을 효율적으로 만들어 주며, 문제를 빠르게 파악할 수 있게 도와줍니다.

JUnit (기존 코드):

@Test
void testStringWithJUnit() {
    String id = "bcd";
    assertTrue(id.contains("a"));
}

실패 시 출력되는 메시지:

expected: <true> but was: <false>

AssertJ (AssertJ 코드):

@Test
void testStringWithAssertJ() {
    String id = "bcd";
    assertThat(id).contains("a");
}

실패 시 출력되는 메시지:

Expecting: 
<"abc">
to contain: 
<"a">

비교:

  • JUnit: 실패 시 expectedactual 값만 비교되며, 오류의 원인에 대한 추가적인 정보는 부족합니다.
  • AssertJ: 실패 시 ExpectedActual 값을 명확하게 구분해 보여줍니다. id가 "a"를 포함할 것 이라고 기대했지만 그렇지 않다는 메세지 덕분에 실패한 원인을 보다 정확하게 알 수 있습니다.

따라서, AssertJ는 실패 메시지가 구체적이고 디버깅을 더 쉽게 만들어 줍니다.

(3) AssertJ의 장점

  • 가독성: 자연어에 가까운 메서드 체이닝으로 테스트 코드를 읽기 쉽고 간결하게 작성할 수 있습니다.
  • 유연성: 숫자, 문자열, 컬렉션, 예외 등 다양한 데이터 타입에 대한 검증을 제공하며, 복잡한 조건을 쉽게 표현할 수 있습니다.
  • 확장성: 커스텀 assertion을 정의할 수 있어 프로젝트 요구사항에 맞는 검증을 수행할 수 있습니다.
  • 유지보수성: 명확한 오류 메시지 덕분에 문제 원인을 빠르게 파악하고 수정할 수 있어 유지보수성이 향상됩니다.

3. AssertJ에서 자주 사용되는 메서드

메서드설명예제 코드
isEqualTo(expected)값이 예상 값과 같은지 확인assertThat(actual).isEqualTo(42);
isNotEqualTo(expected)값이 예상 값과 다른지 확인assertThat(actual).isNotEqualTo(10);
isTrue() / isFalse()값이 true 또는 false인지 확인assertThat(actual).isTrue();
isNull() / isNotNull()값이 null인지 또는 아닌지 확인assertThat(actual).isNotNull();
contains(value)문자열이나 컬렉션에 값이 포함되는지 확인assertThat(actual).contains("Java");
doesNotContain(value)문자열이나 컬렉션에 값이 없는지 확인assertThat(actual).doesNotContain("Python");
hasSize(size)컬렉션 또는 배열의 크기를 검증assertThat(actual).hasSize(3);
startsWith(prefix)문자열이 특정 접두사로 시작하는지 확인assertThat(actual).startsWith("Hello");
endsWith(suffix)문자열이 특정 접미사로 끝나는지 확인assertThat(actual).endsWith("World");
extracting(extractor)객체의 특정 속성을 추출하여 검증assertThat(actual).extracting(Person::getName).isEqualTo("John");

4. 예제 코드

(1) 숫자 검증

@Test
void testNumber() {
    int actual = 42;
    assertThat(actual)
        .isGreaterThan(30)
        .isLessThan(50)
        .isPositive()
        .isNotZero();
}

(2) 문자열 검증

@Test
void testString() {
    String actual = "AssertJ is powerful!";
    assertThat(actual)
        .startsWith("AssertJ")
        .endsWith("powerful!")
        .contains("is")
        .doesNotContain("weak")
        .matches(".*powerful!$");
}

(3) 컬렉션 검증

@Test
void testCollection() {
    List<String> actual = List.of("Java", "Spring", "AssertJ");
    assertThat(actual)
        .isNotEmpty()
        .hasSize(3)
        .contains("Spring")
        .doesNotContain("Python")
        .containsExactly("Java", "Spring", "AssertJ");
}

(4) 예외 검증

@Test
void testException() {
    assertThatThrownBy(() -> {
        throw new IllegalArgumentException("Invalid input");
    })
    .isInstanceOf(IllegalArgumentException.class)
    .hasMessageContaining("Invalid");
}

(5) 객체 속성 검증

@Test
void testObject() {
    Person person = new Person("John", 30);
    assertThat(person)
        .extracting(Person::getName, Person::getAge)
        .containsExactly("John", 30);
}

마무리하며

AssertJ로 좀 더 간결하고 가독성 높은 테스트 코드를 편리하게 써봅시다. 🚀

profile
하리보의 개발 블로그

0개의 댓글