스프링 부트 3는 효율적인 애플리케이션 개발을 지원하는 동시에, 안정적이고 신뢰성 높은 코드를 작성할 수 있도록 다양한 테스트 기능을 제공합니다. 유닛 테스트(Unit Test)는 그중에서도 가장 기본적이고 중요한 단계로, 개별적인 메서드나 클래스 단위에서 로직의 정확성을 검증합니다. 이 글에서는 스프링 부트 3에서 유닛 테스트를 작성하는 방법과 기법에 대해 살펴보며, 실용적인 예제 3가지를 포함하여 상세히 설명하겠습니다.
1. 유닛 테스트의 중요성과 목적
**유닛 테스트(Unit Test)**는 소프트웨어 개발 과정에서 개별 모듈의 동작을 검증하는 테스트입니다. 이는 다음과 같은 이유로 중요합니다:
- 버그 사전 방지: 코드 작성 초기부터 오류를 발견하여 수정 비용을 줄입니다.
- 코드 신뢰성 확보: 코드가 의도한 대로 동작함을 보장합니다.
- 리팩토링 안전성: 기존 테스트를 통해 리팩토링 시도 시 코드 안정성을 확인할 수 있습니다.
- 문서화 역할: 테스트 코드는 동작 방식에 대한 훌륭한 설명서 역할을 합니다.
2. 스프링 부트 3에서의 테스트 환경 설정
스프링 부트 3는 테스트를 위한 의존성과 도구를 간단히 통합할 수 있습니다. JUnit 5가 기본 테스트 플랫폼으로 포함되어 있으며, 모킹(mocking)을 위한 Mockito, 가짜 객체를 제공하는 Spring Test 등도 사용 가능합니다.
2.1 의존성 추가
build.gradle 또는 pom.xml 파일에 테스트 관련 의존성을 추가합니다.
Gradle:
dependencies {
testImplementation 'org.springframework.boot:spring-boot-starter-test'
}
Maven:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
3. 유닛 테스트 작성 기본 구조
스프링 부트 3에서 유닛 테스트를 작성할 때 주로 JUnit 5를 사용합니다. 기본적인 유닛 테스트의 구조는 다음과 같습니다:
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class SampleServiceTest {
@Test
void exampleTest() {
// Given: 테스트 준비
int input = 5;
// When: 테스트 대상 실행
int result = input * 2;
// Then: 결과 검증
assertEquals(10, result);
}
}
4. 스프링 부트 3에서 유닛 테스트 주요 기법
스프링 부트 애플리케이션에서 자주 사용되는 유닛 테스트 기법은 크게 다음 세 가지로 나뉩니다:
- 서비스 계층 테스트
- 컨트롤러 테스트
- 레포지토리 테스트
4.1 서비스 계층 테스트
서비스 계층은 핵심 비즈니스 로직이 구현되는 부분으로, 단독으로 테스트하기 위해 모킹(Mock)을 활용합니다.
예제: 서비스 계층 유닛 테스트
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;
class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserService userService;
@Test
void testFindUserById() {
// Given
MockitoAnnotations.openMocks(this);
User mockUser = new User(1L, "John Doe");
when(userRepository.findById(1L)).thenReturn(Optional.of(mockUser));
// When
User result = userService.findUserById(1L);
// Then
assertNotNull(result);
assertEquals("John Doe", result.getName());
verify(userRepository, times(1)).findById(1L);
}
}
4.2 컨트롤러 테스트
컨트롤러는 REST API의 진입점으로, 요청과 응답의 정확성을 검증하기 위해 MockMvc를 사용합니다.
예제: 컨트롤러 유닛 테스트
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
void testGetUser() throws Exception {
// When & Then
mockMvc.perform(get("/users/1"))
.andExpect(status().isOk());
}
}
4.3 레포지토리 테스트
스프링 데이터 JPA를 사용하는 경우, 레포지토리 테스트를 통해 데이터베이스 연산이 의도한 대로 작동하는지 확인할 수 있습니다. @DataJpaTest를 활용합니다.
예제: 레포지토리 테스트
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import static org.junit.jupiter.api.Assertions.*;
@DataJpaTest
class UserRepositoryTest {
@Autowired
private UserRepository userRepository;
@Test
void testSaveUser() {
// Given
User user = new User(null, "Jane Doe");
// When
User savedUser = userRepository.save(user);
// Then
assertNotNull(savedUser.getId());
assertEquals("Jane Doe", savedUser.getName());
}
}
5. 유닛 테스트를 효과적으로 관리하는 팁
- 단일 책임 원칙 준수: 하나의 테스트는 하나의 기능만 검증해야 합니다.
- 테스트 독립성 유지: 각 테스트는 서로 독립적으로 실행되어야 합니다.
- 모킹 활용: 외부 의존성을 제거하여 테스트 대상에 집중합니다.
- 코드 커버리지 도구 사용: JaCoCo와 같은 도구로 테스트 커버리지를 측정합니다.
6. 결론
스프링 부트 3의 유닛 테스트는 애플리케이션의 품질을 유지하고 개선하는 데 필수적인 요소입니다. 본 글에서 소개한 서비스, 컨트롤러, 레포지토리 계층의 테스트 기법과 예제를 활용하면 코드 신뢰성을 높이고 유지보수성을 확보할 수 있습니다. 스프링 부트의 강력한 테스트 도구들을 적극 활용하여 안정적이고 효율적인 애플리케이션 개발에 한 걸음 더 나아가길 바랍니다.
'스프링 부트3' 카테고리의 다른 글
HTTP/2 설정과 최적화 (0) | 2024.12.06 |
---|---|
Spring Boot 3의 Spring Native (0) | 2024.12.06 |
스프링 부트 3와 Flyway: 데이터베이스 마이그레이션을 위한 완벽한 조합 (1) | 2024.12.06 |
스프링 부트 3에서 데이터베이스 마이그레이션 (0) | 2024.12.06 |
스프링 부트 3의 Reactive Programming (0) | 2024.12.06 |