본문 바로가기
Framework || Library/Spring

Mockito를 알아보자

by 시니성 2023. 9. 12.

1. Mockito란 무엇인가?

Mockito는 Java와 Kotlin에서 주로 사용되는 mocking 프레임워크입니다. Mocking은 단위 테스트에서 외부 의존성 또는 실제 구현을 가진 객체를 대체하는 것을 의미합니다. Mockito를 사용하면 실제 코드와 독립적으로 테스트를 수행할 수 있으며, 원하는 동작을 모방한 객체를 쉽게 생성할 수 있습니다.

2. Mockito의 특장점

  • 의존성 분리: 실제 서비스, 데이터베이스, 외부 API 등의 의존성에서 독립적으로 테스트 코드를 작성할 수 있습니다.
  • 유연한 동작 설정: 다양한 조건과 상황에 따라 mock 객체의 동작을 손쉽게 설정할 수 있습니다.
  • 명확한 검증: 특정 메서드가 어떻게 호출되었는지, 몇 번 호출되었는지 등의 상세한 검증이 가능합니다.
  • 코드 간결성: 직관적인 API를 통해 테스트 코드를 간결하게 유지할 수 있습니다.

3. Mockito의 given / when / then

  • given: 테스트를 위한 사전 조건을 설정하는 단계입니다. 예를 들어 mock 객체가 어떤 메서드 호출에 어떻게 응답할 것인지를 설정합니다.
  • when: 실제로 테스트하고자 하는 코드 또는 로직을 실행하는 단계입니다.
  • then: 실행 결과를 검증하는 단계입니다. 특정 메서드가 원하는 방식으로 호출되었는지, 원하는 결과가 나왔는지 등을 확인합니다.

가상 시나리오 및 예시코드

상황: Spring Boot와 JPA를 사용하여 개발된 서비스에서, 사용자의 주문 내역을 가져오는 기능을 테스트하려고 합니다.

// Kotlin + Spring + JPA

// 서비스 클래스 정의
@Service
class OrderService(private val orderRepository: OrderRepository) {

    // 사용자 ID에 따른 주문 내역을 반환하는 메서드
    fun getUserOrders(userId: Long): List<Order> {
        // JPA 리포지토리 메서드 호출
        return orderRepository.findByUserId(userId)
    }
}

// JPA 리포지토리 인터페이스
interface OrderRepository : JpaRepository<Order, Long> {
    // 사용자 ID를 기준으로 주문 내역을 검색하는 메서드
    fun findByUserId(userId: Long): List<Order>
}

// 주문 데이터 클래스
data class Order(val id: Long, val userId: Long, val item: String, val price: Double)

이 코드를 Mockito를 사용하여 테스트하려면:

// Spring Boot 테스트 어노테이션
@SpringBootTest
internal class OrderServiceTest {

    // 테스트 대상 서비스를 주입하기 위한 어노테이션
    @InjectMocks
    lateinit var orderService: OrderService

    // Mock 객체를 생성하기 위한 어노테이션
    @Mock
    lateinit var orderRepository: OrderRepository

    // 테스트 메서드
    @Test
    fun `getUserOrders returns correct orders`() {
        // given

        // 테스트를 위한 사용자 ID 정의
        val userId = 1L
        // mock 객체의 예상 반환값 정의
        val mockOrders = listOf(Order(1L, userId, "Item A", 100.0))
        // mock 객체의 메서드 호출에 대한 반환값 설정
        given(orderRepository.findByUserId(userId)).willReturn(mockOrders)

        // when

        // 테스트 대상 메서드 호출
        val result = orderService.getUserOrders(userId)

        // then

        // 반환된 결과와 예상값 비교
        assertThat(result).isEqualTo(mockOrders)
    }
}

  • 설명:
    • @InjectMocks는 테스트 대상이 되는 OrderService를 초기화하면서, 모든 mock 필드를 해당 서비스에 주입합니다.
    • @MockOrderRepository 인터페이스의 mock 객체를 생성합니다.
    • given에서는 mock 객체가 어떻게 동작해야 하는지 정의합니다. 여기서는 findByUserId가 호출되면 mockOrders를 반환하도록 설정했습니다.
    • when에서는 실제 로직을 실행합니다.
    • then에서는 실행 결과를 검증합니다.

이 테스트는 실제 데이터베이스와 상호작용하지 않기 때문에 빠르게 실행되며, 특정 조건과 상황에서의 OrderService의 동작을 정확히 검증할 수 있습니다.