본문 바로가기
스프링 부트3

스프링 부트 3의 유닛 테스트 기법

by 굿센스굿 2024. 12. 6.
반응형

 

스프링 부트 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에서 유닛 테스트 주요 기법

스프링 부트 애플리케이션에서 자주 사용되는 유닛 테스트 기법은 크게 다음 세 가지로 나뉩니다:

  1. 서비스 계층 테스트
  2. 컨트롤러 테스트
  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의 유닛 테스트는 애플리케이션의 품질을 유지하고 개선하는 데 필수적인 요소입니다. 본 글에서 소개한 서비스, 컨트롤러, 레포지토리 계층의 테스트 기법과 예제를 활용하면 코드 신뢰성을 높이고 유지보수성을 확보할 수 있습니다. 스프링 부트의 강력한 테스트 도구들을 적극 활용하여 안정적이고 효율적인 애플리케이션 개발에 한 걸음 더 나아가길 바랍니다.

반응형