[Mock] 스프링 환경에서 외부시스템 테스트하기

y001·2025년 1월 27일
post-thumbnail

1. Mock 객체 사용 여부

1.1 Mock을 사용하는 경우

Mock 객체는 외부 시스템과의 의존성을 제거하여 독립적인 단위 테스트를 수행할 수 있도록 합니다. 다음과 같은 경우 Mock을 사용하는 것이 효과적입니다:

  • 외부 API 호출, 이메일 전송, 데이터베이스 액세스 등 네트워크나 IO 작업이 포함된 경우.
  • 테스트 환경에서 독립적으로 동작해야 하는 비즈니스 로직을 검증할 때.
  • 실행 속도를 향상시키고 테스트 격리를 보장하고자 할 때.

1.2 Mock을 사용하지 않는 경우

  • 순수한 비즈니스 로직을 검증하는 경우.
  • 내부 연산(예: 데이터 변환, 컬렉션 조작 등)을 검증할 때.
  • 실제 객체의 동작을 그대로 테스트하는 것이 중요한 경우.

1.3 Classicist vs Mockist 접근법

  • Classicist(고전적 접근법): 가능한 한 실제 객체를 사용하여 테스트하며, Mocking은 외부 의존성 제거 용도로만 활용.
  • Mockist(모키스트 접근법): 모든 의존성을 Mocking하여 독립적이고 빠른 테스트를 추구.

2. Mockito의 주요 어노테이션

Mockito는 다양한 테스트 시나리오를 지원하는 어노테이션을 제공합니다.

2.1 독립적인 Mock 객체

  • @Mock: Mock 객체를 생성하여 동작을 정의할 수 있습니다.

    @Mock
    private OrderRepository orderRepository;
  • @Spy: 실제 객체를 생성하면서 필요한 부분만 Mocking이 가능합니다.

    @Spy
    private List<String> spyList = new ArrayList<>();
  • @InjectMocks: @Mock 또는 @Spy로 생성된 객체를 주입하여 테스트 대상 객체를 초기화합니다.

    @InjectMocks
    private OrderService orderService;

2.2 스프링 컨텍스트 기반 Mocking

  • @MockBean: 스프링 컨텍스트에 Mock 객체를 등록하여 통합 테스트에서 사용됩니다.

    @MockBean
    private OrderRepository orderRepository;
  • @SpyBean: 실제 스프링 빈을 감싸서 부분적인 Mocking이 가능합니다.

    @SpyBean
    private OrderService orderService;

3. BDD 스타일과 Mockito.when()

Mockito는 전통적인 when() 메서드와 BDD 스타일의 given() 메서드를 지원합니다.

  • Mockito.when(): 특정 조건에서 Mock 객체의 동작을 정의합니다.

    when(orderRepository.findById(1L)).thenReturn(Optional.of(mockOrder));
  • BDDMockito.given(): BDD 스타일의 가독성을 높이기 위한 API입니다.

    given(orderRepository.findById(1L)).willReturn(Optional.of(mockOrder));

4. SnsService 테스트 예제

SnsService는 메세지를 전송하는 기능을 수행하며, 외부 시스템과 연계되기 때문에 Mock 객체를 사용하여 테스트해야 합니다.

4.1 Mock 객체를 활용한 단위 테스트

@Mock
private SnsClient emailClient;

@InjectMocks
private SnsService emailService;

@Test
void testSendEmail() {
    // Given
    given(emailClient.send("user123", "Test Notification")).willReturn(true);

    // When
    boolean result = emailService.sendMessage("user123", "Test Notification");

    // Then
    assertTrue(result);
    verify(emailClient).send("user123", "Test Notification");
}

이 테스트는 SnsClient를 Mocking하여 실제 메세지 전송 없이 SnsService의 로직을 검증하는 방법을 보여줍니다.


📌 이 글은 TDD 강의를 학습한 내용을 바탕으로 재구성하였습니다. 문제가 되는 부분이 있다면 수정하겠습니다.

0개의 댓글