AssertJ 소개

AssertJ는 테스트 코드의 가독성을 극대화하기 위해 설계된 라이브러리입니다. 메서드 체이닝을 통해 영어 문장처럼 읽히는 테스트 작성이 가능하며, IDE 자동 완성에 최적화되어 있습니다.

의존성 추가

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

Spring Boot 프로젝트에서는 spring-boot-starter-test에 포함되어 있어 별도 추가 불필요합니다.

기본 사용법

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

assertThat(actual).isEqualTo(expected);

기본 단정문

공통 검증 메서드

메서드 설명
isEqualTo 객체의 동등성 비교 (equals 사용)
isNotEqualTo 객체가 같지 않음을 확인
isSameAs 객체의 동일성 비교 (== 사용)
isNotSameAs 객체가 동일하지 않음
isNull Null임을 확인
isNotNull Null이 아님을 확인
isInstanceOf 특정 클래스의 인스턴스인지 확인
isExactlyInstanceOf 정확히 특정 클래스 타입인지 확인 (상속 무시)
as 실패 시 출력될 설명 메시지 설정
describedAs as와 동일 (별칭)

코드 예제

@Test
void basicAssertions() {
    String actual = "Spring Boot";
    String expected = "Spring Boot";
    
    // 동등성 비교
    assertThat(actual).isEqualTo(expected);
    
    // 동일성 비교 (같은 객체 참조)
    assertThat(actual).isSameAs(expected); // String 리터럴은 같은 참조
    
    // Null 검증
    String nullStr = null;
    assertThat(nullStr).isNull();
    assertThat(actual).isNotNull();
    
    // 타입 검증
    assertThat(actual).isInstanceOf(String.class);
    assertThat(actual).isExactlyInstanceOf(String.class);
    
    // 설명 메시지 추가
    assertThat(actual)
        .as("Spring Boot 문자열 검증")
        .isEqualTo(expected);
}

@Test
void inheritanceTypeChecking() {
    List<String> arrayList = new ArrayList<>();
    
    // ArrayList는 List의 구현체이므로 true
    assertThat(arrayList).isInstanceOf(List.class);
    
    // 정확히 ArrayList 타입인지 확인
    assertThat(arrayList).isExactlyInstanceOf(ArrayList.class);
}

문자열 검증

문자열 전용 메서드

메서드 설명
isEmpty 빈 문자열인지 확인
isNotEmpty 빈 문자열이 아닌지 확인
isBlank 빈 문자열이거나 공백만 있는지 확인
isNotBlank 공백이 아닌 문자가 있는지 확인
contains 특정 문자열을 포함하는지 확인
containsIgnoringCase 대소문자 무시하고 포함 여부 확인
doesNotContain 특정 문자열을 포함하지 않는지 확인
startsWith 특정 문자열로 시작하는지 확인
endsWith 특정 문자열로 끝나는지 확인
matches 정규표현식과 일치하는지 확인
doesNotMatch 정규표현식과 일치하지 않는지 확인
hasSize 문자열 길이 확인
hasSameSizeAs 다른 문자열과 같은 길이인지 확인
isEqualToIgnoringCase 대소문자 무시하고 동등성 비교
isEqualToIgnoringWhitespace 공백 무시하고 동등성 비교
containsOnlyDigits 숫자만 포함하는지 확인
containsOnlyWhitespaces 공백만 포함하는지 확인
containsSequence 여러 문자열이 순서대로 포함되는지 확인
containsSubsequence 여러 문자열이 순서대로 포함 (중간에 다른 문자 허용)

코드 예제

@Test
void stringAssertions() {
    String email = "user@example.com";
    String password = "  Pass123!  ";
    String message = "Spring Boot 3.4 Release";
    
    // 기본 검증
    assertThat(email)
        .isNotEmpty()
        .isNotBlank()
        .contains("@")
        .startsWith("user")
        .endsWith(".com")
        .hasSize(17);
    
    // 정규표현식 검증
    assertThat(email).matches("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$");
    
    // 대소문자 무시 검증
    assertThat(message)
        .containsIgnoringCase("spring")
        .isEqualToIgnoringCase("SPRING BOOT 3.4 RELEASE");
    
    // 공백 처리
    assertThat(password.trim())
        .isEqualTo("Pass123!")
        .containsOnlyOnce("!")
        .doesNotContainAnyWhitespaces();
    
    // 복합 검증
    assertThat("Spring Boot 3.4")
        .isNotBlank()
        .contains("Boot")
        .doesNotContain("Java 8")
        .startsWith("Spring")
        .endsWith("3.4")
        .hasSize(15)
        .matches("^Spring Boot \\d\\.\\d$");
}

@Test
void stringSequenceAssertions() {
    String text = "The quick brown fox jumps over the lazy dog";
    
    // 순차적으로 포함되는지 확인
    assertThat(text)
        .containsSequence("quick", "brown", "fox")
        .containsSubsequence("The", "fox", "dog");
    
    // 숫자만 포함
    assertThat("12345").containsOnlyDigits();
    
    // 공백만 포함
    assertThat("   ").containsOnlyWhitespaces();
}

@Test
void stringIgnoringCases() {
    // 대소문자와 공백을 모두 무시한 비교
    assertThat("  Hello   World  ")
        .isEqualToIgnoringWhitespace("Hello World")
        .isEqualToIgnoringCase("  HELLO   WORLD  ");
}

숫자 검증

숫자 전용 메서드

메서드 설명
isZero 0인지 확인
isNotZero 0이 아닌지 확인
isOne 1인지 확인
isPositive 양수인지 확인
isNegative 음수인지 확인
isNotPositive 양수가 아닌지 확인 (0 또는 음수)
isNotNegative 음수가 아닌지 확인 (0 또는 양수)
isGreaterThan 특정 값보다 큰지 확인
isGreaterThanOrEqualTo 특정 값보다 크거나 같은지 확인
isLessThan 특정 값보다 작은지 확인
isLessThanOrEqualTo 특정 값보다 작거나 같은지 확인
isBetween 두 값 사이에 있는지 확인 (경계값 포함)
isStrictlyBetween 두 값 사이에 있는지 확인 (경계값 제외)
isCloseTo 특정 값에 근접한지 확인 (오차 범위 지정)
isNotCloseTo 특정 값에 근접하지 않은지 확인
isEqualByComparingTo compareTo 메서드로 비교

코드 예제

@Test
void integerAssertions() {
    int age = 25;
    int score = 0;
    int debt = -1000;
    
    // 기본 숫자 검증
    assertThat(age)
        .isPositive()
        .isNotZero()
        .isGreaterThan(18)
        .isLessThan(100)
        .isBetween(20, 30);
    
    assertThat(score)
        .isZero()
        .isNotPositive()
        .isNotNegative();
    
    assertThat(debt)
        .isNegative()
        .isLessThan(0);
    
    // 범위 검증
    assertThat(age)
        .isBetween(20, 30)           // 20 <= age <= 30
        .isStrictlyBetween(20, 30);  // 20 < age < 30
}

@Test
void doubleAssertions() {
    double price = 99.99;
    double pi = 3.14159;
    
    // 실수 정밀도 비교
    assertThat(price)
        .isCloseTo(100.0, within(0.1))
        .isCloseTo(100.0, withPercentage(1.0));
    
    assertThat(pi)
        .isCloseTo(3.14, within(0.01))
        .isBetween(3.0, 3.2);
}

@Test
void bigDecimalAssertions() {
    BigDecimal amount1 = new BigDecimal("1.00");
    BigDecimal amount2 = new BigDecimal("1.0");
    
    // BigDecimal은 scale이 달라도 값이 같으면 true
    assertThat(amount1)
        .isEqualByComparingTo(amount2)
        .isNotEqualTo(amount2);  // equals는 scale도 비교하므로 false
    
    assertThat(amount1)
        .isGreaterThanOrEqualTo(new BigDecimal("0.99"))
        .isLessThan(new BigDecimal("1.01"));
}

@Test
void percentageAssertions() {
    double actual = 100.0;
    
    // 퍼센트 오차 범위로 비교
    assertThat(actual)
        .isCloseTo(95.0, withPercentage(10.0))   // 10% 오차 허용
        .isNotCloseTo(80.0, withPercentage(10.0)); // 10% 오차 범위 밖
}