프로그래머스/Spring

[Spring] 단위 테스트(Unit Test) vs 통합 테스트(Integration Test)

annovation 2025. 3. 28. 08:50

단위 테스트(Unit Test)

  • 단위 테스트는 DB 없이 서비스 로직을 검증하는 테스트이다.
  • Spring을 실행하지 않고 Mockito로 필요한 객체를 Mock 처리해서 사용한다.

📌 단위 테스트 코드 예시

@ExtendWith(MockitoExtension.class)  // Spring 실행 없이 Mockito만 사용
class UserServiceTest {

    @Mock  // 가짜 객체(Mock) 생성
    private UserRepository userRepository;

    @InjectMocks  // UserService가 위의 Mock 객체를 사용하도록 설정
    private UserService userService;

    @Test
    void findUserById() {
        // given
        Long userId = 1L;
        UserEntity mockUser = new UserEntity(userId, "ann", "ann@email.com");
        
        // findById() 호출 시, 실제 DB가 아니라 미리 정의한 Mock 데이터를 반환하도록 설정
        when(userRepository.findById(userId)).thenReturn(Optional.of(mockUser));

        // when
        Optional<UserEntity> foundUser = userService.findById(userId);

        // then
        assertNotNull(foundUser);
        assertEquals("ann", foundUser.get().getUsername());

        // findById()가 한 번만 호출되었는지 검증
        verify(userRepository, times(1)).findById(userId);
    }
}
  • 정적 임포트가 적용된 경우 : import static org.mockito.Mockito.*; → Mockito Class의 모든 static Method를 import
  • 그래서 Mockito.when() 대신 when()만 사용해도 동일하게 동작

💡 특징

  • @Mock으로 가짜 UserRepository 객체를 만들어서 findById() 실행 시 가짜 데이터를 반환하도록 함
  • DB 없이 서비스 로직만 검증하므로 속도가 빠름

통합 테스트(Integration Test)

  • 통합 테스트는 실제 Spring Context를 로드하고 DB와 연결하여 동작을 검증하는 테스트이다.

📌 통합 테스트 코드 예시

@SpringBootTest
@Transactional  // 테스트 후 DB 롤백
class UserServiceIntegrationTest {

    @Autowired  // 진짜 빈(Bean)을 주입
    private UserService userService;

    @Autowired
    private UserRepository userRepository;

    @Test
    void createUser() {
        // given
        String username = "testUser";
        String email = "test@email.com";

        // when
        UserEntity newUser = userService.createUser(username, email);

        // then
        assertNotNull(newUser.getId());
        assertEquals(username, newUser.getUsername());

        // 실제 DB에서 조회하여 확인
        Optional<UserEntity> savedUser = userRepository.findById(newUser.getId());
        assertTrue(savedUser.isPresent());
    }
}

 

💡 특징

  • @SpringBootTest를 사용하여 실제 애플리케이션 환경을 로드
  • @Transactional을 사용하면 테스트가 끝난 후 자동으로 DB 롤백
  • @Autowired를 사용하여 실제 UserService, UserRepository 빈을 주입받음
  • 단위 테스트보다 속도가 느림 (DB I/O 발생)

단위 테스트(Unit Test) vs 통합 테스트(Integration Test)

구분 단위 테스트 (Unit Test) 통합 테스트 (Integration Test)
목적 개별 메서드/클래스를 독립적으로 검증 여러 컴포넌트(Spring, DB, API 등) 간의 동작 검증
DB 사용 여부 ❌ 사용 안 함 (Mockito로 Mocking) ✅ 사용 (H2, MySQL 등 실제 DB)
Spring Context 로드 여부 ❌ 로드 안 함 (@SpringBootTest 없음) ✅ 로드함 (@SpringBootTest 사용)
속도 ⏩ 빠름 (ms 단위) ⏳ 느림 (DB I/O 발생)
테스트 코드 스타일 @Mock으로 Mock 객체 사용 실제 @Repository, @Service 등을 실행
대표적인 테스트 툴 Mockito, JUnit SpringBootTest, Testcontainers

용도

사용 상황 추천 테스트
서비스 로직(비즈니스 로직)만 검증 ✅ 단위 테스트 (Mockito)
DB 없이 빠르게 검증해야 함 ✅ 단위 테스트 (Mockito)
Controller, Service, Repository가 잘 연결되었는지 확인해야 함 ✅ 통합 테스트 (SpringBootTest)
실제 DB 연동이 필요한 경우 ✅ 통합 테스트 (SpringBootTest)
테스트 환경에서도 실제 쿼리가 실행되는지 확인해야 함 ✅ 통합 테스트 (SpringBootTest)

요약

Mockito를 사용하면 단위 테스트 (DB 없이 로직 검증)
Spring + DB를 사용하면 통합 테스트 (전체 동작 검증)
일반적으로 단위 테스트를 많이 작성하고, 중요한 기능만 통합 테스트로 검증


출처

OpenAI ChatGPT (https://openai.com)

'프로그래머스 > Spring' 카테고리의 다른 글

[Spring] MockMvc  (0) 2025.04.16
[Lombok] @Data  (1) 2025.04.13
[Spring] JPA Specification  (1) 2025.02.19
[Spring] Bean  (1) 2025.02.12
[Spring] 페이징 (Paiging) 주요 메서드  (0) 2025.02.10