[Java] JUnit

배창민·2025년 9월 19일
post-thumbnail

JUnit · AssertJ · TDD

핵심: JUnit은 자바 단위 테스트 표준 프레임워크.
초기 버그를 빠르게 잡고, TDD(테스트 주도 개발)를 실천하는 데 필수 도구


1) JUnit 빠르게 훑기

  • 정의: 자바용 단위 테스트 프레임워크. Kent Beck & Erich Gamma 개발.
  • 목적: 작은 단위(메서드/컴포넌트)별로 독립 테스트 → 안정성 보장 & 회귀 버그 방지.

JUnit4 vs JUnit5

비교 항목JUnit 4JUnit 5 (Jupiter)
패키지org.junitorg.junit.jupiter
생명주기 애노테이션@Before, @After@BeforeEach, @AfterEach
클래스 전/후@BeforeClass, @AfterClass@BeforeAll, @AfterAll
비활성화@Ignore@Disabled
어설션Assert.assertEquals()Assertions.assertEquals()

2) 단위 테스트란?

  • 정의: 시스템의 “가장 작은 단위(함수/메서드/클래스)”를 독립적으로 검증.
  • 효과: 빠른 피드백, 리팩토링 자신감, 문서 역할(사례로 명세화).

3) JUnit5 기본 문법

자주 쓰는 애노테이션

  • @Test : 테스트 메서드
  • @BeforeEach / @AfterEach : 각 테스트 전/후
  • @BeforeAll / @AfterAll : 클래스 단 한 번 전/후(정적 메서드)
  • @DisplayName("설명") : 보기 좋은 테스트 이름
  • @RepeatedTest(n) : 반복 실행

자주 쓰는 어설션

  • assertEquals(expected, actual)
  • assertTrue(condition) / assertFalse(condition)
  • assertNotNull(obj) / assertNull(obj)
  • assertAll(…) : 여러 어설션 한 번에

4) JUnit 기본 예제

4-1. 가장 단순한 테스트

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

class ExampleTest {

    @Test
    void testAddition() {
        int result = 1 + 1;
        assertEquals(2, result);
    }
}

4-2. 생명주기 활용

import org.junit.jupiter.api.*;
import java.util.*;

class ExampleTest {

    private List<String> list;

    @BeforeEach
    void setUp() {
        list = new ArrayList<>();
        list.add("Hello");
    }

    @AfterEach
    void tearDown() {
        list.clear();
    }

    @Test
    void testList() {
        assertEquals(1, list.size());
        assertTrue(list.contains("Hello"));
    }
}

4-3. assertAll()로 다중 검증

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

class AssertAllExample {

    @Test
    void testPersonAttributes() {
        Person person = new Person("John", 25);

        assertAll("Person",
            () -> assertEquals("John", person.getName()),
            () -> assertEquals(25, person.getAge()),
            () -> assertNotNull(person)
        );
    }
}

4-4. 예외 검증 (assertThrows)

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

class ExceptionTest {

    @Test
    void testException() {
        IllegalArgumentException ex = assertThrows(
            IllegalArgumentException.class,
            () -> { throw new IllegalArgumentException("null"); }
        );
        assertEquals("null", ex.getMessage()); // 또는 assertNotNull(ex.getMessage());
    }
}

5) AssertJ로 더 읽기 좋은 테스트

JUnit의 어설션을 플루언트 API로 보강 → 가독성/표현력 ↑

예제

import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.*;

class AssertJExample {

    @Test
    void testString() {
        String str = "Hello, AssertJ!";
        assertThat(str)
            .isNotEmpty()
            .contains("Hello")
            .endsWith("AssertJ!");
    }
}

장점

  • 자연어에 가까운 체이닝
  • 컬렉션/예외/시간/경계값 등 풍부한 전용 어설션
  • 사용자 정의 어설션 확장 용이

6) TDD(테스트 주도 개발)와 JUnit

Red → Green → Refactor 세 단계로 설계를 이끈다.

단계설명
🔴 Red실패하는 테스트 먼저 작성
🟢 Green테스트를 통과하는 최소한의 코드 작성
🟡 Refactor중복 제거·가독성 개선·구조 개선

TDD 미니 예시

import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;

class CalculatorTest {

    @Test
    void add() {
        Calculator calc = new Calculator();
        assertEquals(2, calc.add(1, 1));
    }
}

class Calculator {
    int add(int a, int b) {
        return a + b;
    }
}

7) 핵심 요약

  • 테스트는 작고 빠르게 (단위 테스트 우선)
  • 하나의 테스트는 하나의 행동을 검증 (Given-When-Then 서술 추천)
  • 예외/경계/빈 컬렉션/널 등 엣지 케이스 포함
  • 실패 메세지로 의도가 드러나게 작성
  • AssertJ로 가독성 ↑, JUnit5 생명주기로 관리성 ↑
profile
개발자 희망자

0개의 댓글