통합 테스트는 일반적으로 애플리케이션의 여러 계층이 함께 동작하는지 확인하기 위한 테스트이다. 따라서 request -> controller -> service -> repository까지 실제로 호출하는 엔드 투 엔드(End-to-End) 테스트가 주된 목적이다. 그렇다면 "서비스에 대한 통합 테스트"란 어떤 의미인지 혼란스러울 수 있다.
"서비스에 대한 통합 테스트"는 다음 두 가지로 이해할 수 있다:
서비스 계층 중심의 통합 테스트
service -> repository 또는 service -> external API 등 서비스 계층과 통합된 하위 계층을 검증한다.서비스 계층이 복잡한 비즈니스 로직을 포함하는 경우
"서비스에 대한 통합 테스트"는 컨트롤러를 제외하고, 서비스와 하위 계층 간의 상호작용에 초점을 맞춘다.
@SpringBootTest
@Transactional // 테스트 후 데이터 롤백
public class ReservationServiceIntegrationTest {
@Autowired
private ReservationService reservationService;
@Autowired
private ReservationRepository reservationRepository;
@Test
void testCreateReservation() {
// given
ReservationRequestDto request = new ReservationRequestDto("itemName", "userNickname");
// when
ReservationResponseDto response = reservationService.createReservation(request);
// then
assertNotNull(response.getId());
assertEquals("itemName", response.getItemName());
assertEquals("userNickname", response.getUserNickname());
// 데이터가 실제로 저장되었는지 검증
Reservation savedReservation = reservationRepository.findById(response.getId()).orElseThrow();
assertEquals("itemName", savedReservation.getItemName());
}
}
컨트롤러를 호출하지 않는다:
실제 데이터베이스 연동:
서비스 계층의 통합 로직 검증:
| 특징 | 서비스 단위 테스트 | 서비스 통합 테스트 |
|---|---|---|
| 테스트 범위 | 서비스 계층만 테스트 (Mock으로 하위 계층 대체) | 서비스 계층 + 리포지토리 또는 외부 API와 통합 |
| 의존성 | 하위 계층(리포지토리, API 등)은 Mock 또는 Stub 사용 | 실제 리포지토리 또는 외부 API 연동 |
| 속도 | 빠르다 (Mock 사용으로 DB 접근 없음) | 느리다 (실제 DB 또는 외부 호출 필요) |
| 테스트 목적 | 비즈니스 로직 단위 테스트 | 서비스 계층과 하위 계층 간 상호작용 검증 |
| 적용 사례 | 간단한 로직, 하위 계층과 무관한 비즈니스 로직 검증 | 복잡한 로직 또는 리포지토리와 통합된 비즈니스 로직 |
리포지토리와의 상호작용 확인:
외부 API 호출 확인:
복잡한 비즈니스 로직 검증:
@SpringBootTest
@Transactional
public class PaymentServiceIntegrationTest {
@Autowired
private PaymentService paymentService;
@Autowired
private PaymentRepository paymentRepository;
@MockBean // 외부 API는 Mock 처리
private ExternalPaymentGateway paymentGateway;
@Test
void testProcessPayment() {
// given
PaymentRequest request = new PaymentRequest(100, "USD");
when(paymentGateway.process(any(PaymentRequest.class))).thenReturn(new PaymentResponse("SUCCESS"));
// when
PaymentResponse response = paymentService.processPayment(request);
// then
assertEquals("SUCCESS", response.getStatus());
// 데이터베이스 저장 확인
Payment savedPayment = paymentRepository.findAll().get(0);
assertEquals(100, savedPayment.getAmount());
assertEquals("USD", savedPayment.getCurrency());
}
}
서비스 통합 테스트:
service -> repository 또는 service -> external API까지의 상호작용을 테스트한다.엔드 투 엔드 테스트 (E2E):
controller -> service -> repository -> DB까지의 모든 계층이 포함된다.