| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | ||||
| 4 | 5 | 6 | 7 | 8 | 9 | 10 |
| 11 | 12 | 13 | 14 | 15 | 16 | 17 |
| 18 | 19 | 20 | 21 | 22 | 23 | 24 |
| 25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 자바기초
- 자료구조
- 자바
- 객체지향
- 알고리즘공부
- 프로그래머스
- 백준
- HashMap
- 메모리관리
- 멀티스레드
- 자바공부
- 개발자취업
- 코딩공부
- 가비지컬렉션
- Java
- 자바프로그래밍
- 정렬
- 코딩인터뷰
- 파이썬
- 클린코드
- 개발공부
- 자바개발
- 개발자팁
- 코딩테스트팁
- 코딩테스트준비
- JVM
- 예외처리
- 프로그래밍기초
- 알고리즘
- 코딩테스트
- Today
- Total
코드 한 줄의 기록
Java 유닛 테스트 완벽 정리: JUnit 5와 단언(Assertions) 개념부터 실전까지 본문
안녕하세요. 오늘은 JUnit 5와 단언(Assertions)에 대해 깊이 있게 정리해보겠습니다. 처음에는 단순히 테스트를 작성하는 것이 목표였지만, 프로젝트가 진행되면서 더 나은 테스트 코드를 어떻게 작성할 수 있을지에 대해 고민하게 되었어요. 이 글에서는 제가 공부하면서 배운 내용과 실제 프로젝트에 적용한 경험을 바탕으로, 여러분도 효과적인 유닛 테스트를 작성할 수 있도록 최대한 상세히 설명하겠습니다.
유닛 테스트가 정말 필요한가?
코드를 작성할 때마다 느끼는 것이지만, 유닛 테스트는 선택이 아닌 필수입니다. 특히 팀 프로젝트나 장기간 유지보수되는 프로덕션 코드라면 더욱 그렇습니다. 유닛 테스트의 가장 큰 장점은 다음과 같습니다.
첫째, 버그를 조기에 발견할 수 있습니다. 코드를 작성한 직후 바로 테스트함으로써 예상치 못한 엣지 케이스를 빠르게 잡아낼 수 있죠.
둘째, 리팩토링 시 자신감이 생깁니다. 코드를 개선하면서도 기존 기능이 깨지지 않았음을 보장받습니다.
셋째, 문서화 역할을 합니다. 테스트 코드를 읽으면 해당 클래스나 메소드가 어떻게 사용되어야 하는지 명확하게 알 수 있습니다.
저는 처음에는 테스트 코드 작성이 번거롭다고 생각했습니다. 하지만 이를 투자로 생각하니 생각이 달라졌어요. 초기에 테스트를 철저히 작성하면, 나중에 버그 수정과 유지보수에 드는 시간을 훨씬 줄일 수 있거든요.
JUnit 5는 무엇인가?
JUnit 5는 Java의 표준 테스트 프레임워크입니다. JUnit 4에서 JUnit 5로 넘어오면서 많은 개선사항이 있었는데, 가장 눈에 띄는 것은 더 유연한 구조와 강력한 기능들입니다.
JUnit 5의 핵심 특징
JUnit 5는 JUnit Platform, JUnit Jupiter, JUnit Vintage 세 가지 핵심 모듈로 이루어져 있습니다. JUnit Platform은 테스트 실행을 위한 기반을 제공하고, JUnit Jupiter는 새로운 프로그래밍 모델과 확장 모델을 제공합니다. JUnit Vintage는 이전 버전과의 호환성을 유지하죠.
실무에서 가장 많이 사용하는 부분은 JUnit Jupiter입니다.
이 모듈에서 제공하는 주요 기능들을 살펴보면
- @Test: 테스트 메소드임을 명시하는 어노테이션
- @BeforeEach: 각 테스트 메소드 실행 전에 실행되는 메소드
- @AfterEach: 각 테스트 메소드 실행 후에 실행되는 메소드
- @DisplayName: 테스트의 한글 이름을 정의할 수 있는 어노테이션
- 람다 표현식 지원: Java 8의 람다 표현식을 활용한 더 깔끔한 테스트 코드
Maven과 Gradle에서 JUnit 5 설정하기
Maven 설정
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.9.2</version>
<scope>test</scope>
</dependency>
Gradle 설정
testImplementation 'org.junit.jupiter:junit-jupiter:5.9.2'
단언(Assertions)이란? 왜 중요한가?
단언(Assertion)은 테스트의 핵심입니다. 테스트에서 예상되는 결과와 실제 결과가 일치하는지를 검증하는 메커니즘이죠. 단언이 없으면 테스트가 무엇을 검증하는지 알 수 없게 됩니다.
제가 처음 테스트를 작성할 때는 assertEquals와 assertTrue 정도만 알고 있었어요. 하지만 JUnit 5에는 훨씬 다양하고 강력한 단언 메소드들이 있습니다. 이들을 상황에 맞게 사용하면 더 명확하고 읽기 쉬운 테스트를 작성할 수 있습니다.

JUnit 5의 주요 단언 메소드들 상세 가이드
기본 값 비교: assertEquals와 assertNotEquals
@Test
void testBasicEquality() {
int expected = 5;
int actual = 2 + 3;
assertEquals(expected, actual, "2 + 3은 5여야 합니다");
}
@Test
void testNotEquals() {
String expected = "Hello";
String actual = "World";
assertNotEquals(expected, actual, "문자열이 다름을 확인합니다");
}
조건 검증: assertTrue와 assertFalse
@Test
void testConditions() {
int age = 25;
assertTrue(age >= 18, "성인이어야 합니다");
assertFalse(age < 0, "나이는 음수일 수 없습니다");
}
예외 검증: assertThrows
@Test
void testExceptionThrown() {
ArithmeticException exception = assertThrows(
ArithmeticException.class,
() -> { int result = 10 / 0; },
"0으로 나누면 예외 발생"
);
assertEquals("/ by zero", exception.getMessage());
}
그룹 단언: assertAll
@Test
void testGroupedAssertions() {
Person person = new Person("John", "Doe");
assertAll("person properties",
() -> assertEquals("John", person.getFirstName()),
() -> assertEquals("Doe", person.getLastName())
);
}
실전 예제: 계산기 클래스 완전히 테스트하기
public class Calculator {
public int add(int a, int b) { return a + b; }
public int subtract(int a, int b) { return a - b; }
public int multiply(int a, int b) { return a * b; }
public int divide(int a, int b) {
if (b == 0) throw new ArithmeticException("Cannot divide by zero");
return a / b;
}
}
Given-When-Then 패턴으로 테스트 구조화하기
@Test
@DisplayName("사용자 가입 시 이메일 중복을 확인합니다")
void testUserRegistrationWithDuplicateEmail() {
// Given
User existingUser = new User("john@example.com", "John");
userRepository.save(existingUser);
User newUser = new User("john@example.com", "John Doe");
// When, Then
assertThrows(
DuplicateEmailException.class,
() -> userService.register(newUser),
"중복된 이메일로는 가입할 수 없습니다"
);
}
좋은 테스트 작성을 위한 Best Practices
- 하나의 테스트는 하나의 동작만 검증하세요.
- 테스트 데이터는 명확하게 구성하세요.
- 테스트는 독립적으로 유지하세요.
- 경계값을 포함한 다양한 입력을 테스트하세요.
- 예외 상황도 반드시 테스트하세요.

테스트 커버리지 측정하기
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.8</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>test</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
JUnit 5와 단언(Assertions)은 Java 개발자가 반드시 숙달해야 할 도구입니다. 이 글에서 소개한 단언 메소드들을 상황에 맞게 활용하면, 코드의 신뢰성과 품질을 모두 높일 수 있습니다.
다음 글에서는 Mockito를 활용한 고급 테스트 기법이나 Spring Boot 통합 테스트 작성을 다룰 예정입니다. 궁금한 점이 있다면 댓글로 남겨주세요!
Gradle 기본기 완벽 정리: DSL, Task, Dependency 실무 가이드
지난 몇 년간 Java 생태계에서 가장 큰 변화 중 하나가 바로 Gradle의 대중화입니다. 저도 처음 Gradle을 접했을 때는 설정 파일에 뭐가 들어있는지, 왜 이렇게 복잡한지 정말 답답했습니다. 하지만
byteandbit.tistory.com
'JAVA' 카테고리의 다른 글
| Java Maven 기본 완벽 가이드 - POM, 라이프사이클, 좌표 개념 정리 (0) | 2025.12.31 |
|---|---|
| Gradle 기본기 완벽 정리: DSL, Task, Dependency 실무 가이드 (0) | 2025.12.29 |
| [자바/Mockito] 테스트 더블 완벽 정리: Mock과 Stub 차이부터 BDD까지 (0) | 2025.12.28 |
| Java 테스트 코드 작성법: Given-When-Then 패턴과 픽스처 관리 완벽 가이드 (0) | 2025.12.28 |
| Java 코드 커버리지 메트릭, 진짜 알고 사용하고 있나요? (0) | 2025.12.21 |