코딩:개발일지

단위 테스트(Unit Test) vs 통합 테스트(Integration Test) 차이점 정리

ZZJJing 2025. 5. 28. 21:19
반응형

단위 테스트란?

  • 가장 작은 단위의 코드를 테스트
  • 보통 하나의 메서드나 클래스를 테스트
  • 외부 의존성을 Mock으로 대체
  • 빠르고 독립적
  • TDD의 기본

통합 테스트란?

  • 여러 컴포넌트가 함께 동작하는지 테스트
  • 실제 DB, API 등 외부 시스템과 연동
  • 단위 테스트보다 느림
  • 실제 환경과 비슷한 조건에서 테스트

주요 차이점

구분 단위 테스트 통합 테스트

범위 개별 메서드/클래스 여러 컴포넌트
속도 빠름 느림
외부 의존성 Mock 사용 실제 시스템 사용
격리성 완전 격리 부분 격리
복잡도 단순 복잡

Java 단위 테스트 예제

테스트 대상 클래스

public class Calculator {
    public int add(int a, int b) {
        return a + b;
    }
    
    public int divide(int a, int b) {
        if (b == 0) {
            throw new IllegalArgumentException("0으로 나눌 수 없습니다");
        }
        return a / b;
    }
}

JUnit5 단위 테스트

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

class CalculatorTest {
    
    private Calculator calculator = new Calculator();
    
    @Test
    @DisplayName("두 수를 더하면 올바른 결과가 나온다")
    void testAdd() {
        // Given
        int a = 5;
        int b = 3;
        
        // When
        int result = calculator.add(a, b);
        
        // Then
        assertEquals(8, result);
    }
    
    @Test
    @DisplayName("0으로 나누면 예외가 발생한다")
    void testDivideByZero() {
        // Given
        int a = 10;
        int b = 0;
        
        // When & Then
        assertThrows(IllegalArgumentException.class, 
            () -> calculator.divide(a, b));
    }
}

Java 통합 테스트 예제

테스트 대상 서비스 클래스

@Service
public class UserService {
    
    @Autowired
    private UserRepository userRepository;
    
    public User createUser(String name, String email) {
        User user = new User(name, email);
        return userRepository.save(user);
    }
    
    public List<User> getAllUsers() {
        return userRepository.findAll();
    }
}

Spring Boot 통합 테스트

@SpringBootTest
@TestPropertySource(locations = "classpath:application-test.properties")
@Transactional
class UserServiceIntegrationTest {
    
    @Autowired
    private UserService userService;
    
    @Autowired
    private UserRepository userRepository;
    
    @Test
    @DisplayName("사용자 생성 후 DB에서 조회 가능하다")
    void testCreateAndRetrieveUser() {
        // Given
        String name = "김개발";
        String email = "dev@example.com";
        
        // When
        User createdUser = userService.createUser(name, email);
        List<User> allUsers = userService.getAllUsers();
        
        // Then
        assertNotNull(createdUser.getId());
        assertEquals(name, createdUser.getName());
        assertEquals(email, createdUser.getEmail());
        assertTrue(allUsers.contains(createdUser));
    }
}

Mock을 사용한 단위 테스트

@ExtendWith(MockitoExtension.class)
class UserServiceUnitTest {
    
    @Mock
    private UserRepository userRepository;
    
    @InjectMocks
    private UserService userService;
    
    @Test
    @DisplayName("사용자 생성 시 Repository의 save 메서드가 호출된다")
    void testCreateUser() {
        // Given
        String name = "김개발";
        String email = "dev@example.com";
        User expectedUser = new User(name, email);
        expectedUser.setId(1L);
        
        when(userRepository.save(any(User.class)))
            .thenReturn(expectedUser);
        
        // When
        User result = userService.createUser(name, email);
        
        // Then
        assertEquals(expectedUser.getId(), result.getId());
        assertEquals(name, result.getName());
        assertEquals(email, result.getEmail());
        verify(userRepository, times(1)).save(any(User.class));
    }
}

언제 어떤 테스트를 사용할까?

단위 테스트 사용 시기

  • 비즈니스 로직 검증
  • 예외 상황 테스트
  • 빠른 피드백이 필요한 경우
  • TDD 개발 시

통합 테스트 사용 시기

  • 여러 레이어 간 상호작용 확인
  • DB 연동 로직 검증
  • API 엔드투엔드 테스트
  • 실제 환경과 유사한 테스트 필요 시

단위 테스트 작성 팁

  • AAA 패턴 사용 (Arrange, Act, Assert)
  • 테스트 메서드 이름을 명확하게
  • 하나의 테스트는 하나의 검증만
  • 경계값 테스트 필수

통합 테스트 작성 팁

  • @Transactional로 롤백 처리
  • 테스트용 설정 파일 분리
  • 테스트 데이터 초기화 주의
  • 실행 시간 고려해서 필요한 것만

테스트 피라미드

      /\
     /  \  E2E Tests (적음)
    /____\
   /      \
  /        \ Integration Tests (보통)
 /__________\
/            \
Unit Tests (많음)
  • 단위 테스트: 70%
  • 통합 테스트: 20%
  • E2E 테스트: 10%

단위 테스트와 통합 테스트는 각각의 목적이 다르다.

둘 다 중요하지만 단위 테스트를 먼저 탄탄히 하고, 필요한 부분에 통합 테스트를 추가하는 것이 좋다.

빠른 피드백과 안정적인 리팩토링을 위해서는 단위 테스트가 핵심이고,

실제 동작 확인을 위해서는 통합 테스트가 필수다.

 

728x90
반응형