IMCAT.DEV
로그인 가입
Kotlin 중급 테스트

Kotlin 단위 테스트 및 Mockito

Kotlin 단위 테스트 및 Mockito — 중급

단위 테스트 및 Mockito

1. 도입 (왜 배워야 하는가)

단위 테스트(Unit Testing)와 Mockito는 소프트웨어 개발에서 매우 중요한 역할을 합니다. 특히, 코드의 품질과 유지보수성을 높이고, 버그를 사전에 방지하는 데 기여합니다. 실무에서는 개발자가 작성한 코드가 예상대로 작동하는지 검증하기 위해 단위 테스트를 작성하는 것이 필수입니다.

실제로, 단위 테스트를 작성하지 않으면 코드 변경 시 기존 기능이 깨지는 문제를 쉽게 경험할 수 있습니다. 이로 인해 버그가 발생하고, 나중에 이를 수정하는 데 많은 시간과 비용이 소요됩니다. 따라서 단위 테스트와 Mockito를 통해 코드의 신뢰성을 높이는 것이 중요합니다.

2. 핵심 개념 설명

  • 단위 테스트(Unit Testing): 소프트웨어의 각 구성 요소(단위)가 올바르게 작동하는지를 검증하는 테스트입니다. 일반적으로 함수나 메서드 단위로 진행됩니다. 비유하자면, 요리를 할 때 재료가 신선한지, 조리법이 올바른지를 확인하는 것과 같습니다.
  • Mockito: 자바와 Kotlin에서 사용하는 인기 있는 목(mock) 객체 프레임워크입니다. 외부 의존성(예: 데이터베이스, API 호출 등)을 대체하여 테스트할 수 있도록 도와줍니다. 이는 마치 친구에게 질문을 하지 않고도 대화하는 것처럼, 실제 의존성을 사용하지 않고도 코드를 테스트할 수 있게 해줍니다.
  • 용어설명
    단위 테스트특정 단위(함수, 메서드)의 기능을 검증하는 테스트
    목 객체의존성을 대체하기 위해 사용하는 가짜 객체

    3. 기본 코드 예제

    단위 테스트의 기본 사용법을 보여주기 위한 간단한 예제입니다. 아래 코드는 Calculator 클래스를 테스트합니다.

    // Calculator.kt
    class Calculator {
        fun add(a: Int, b: Int): Int {
            return a + b
        }
    }
    
    // CalculatorTest.kt
    import org.junit.Test
    import kotlin.test.assertEquals
    
    class CalculatorTest {
        private val calculator = Calculator()
    
        @Test
        fun testAdd() {
            assertEquals(5, calculator.add(2, 3)) // 2 + 3 = 5
        }
    }

    실행 결과:

    Test passed.
  • Calculator 클래스는 두 수를 더하는 add 메서드를 가지고 있습니다.
  • CalculatorTest 클래스는 JUnit을 사용하여 Calculator의 add 메서드를 테스트합니다.
  • assertEquals(5, calculator.add(2, 3))는 add(2, 3)의 결과가 5와 같은지를 검증합니다.
  • 4. 실전 활용 예제

    예제 1: 쇼핑몰 장바구니

    쇼핑몰에서 장바구니에 아이템을 추가하는 기능을 테스트할 때, 아래와 같이 Mockito를 사용할 수 있습니다.

    // Cart.kt
    class Cart(private val discountService: DiscountService) {
        private val items = mutableListOf<Item>()
    
        fun addItem(item: Item) {
            items.add(item)
        }
    
        fun applyDiscount(code: String) {
            val discount = discountService.getDiscount(code)
            // 할인 적용 로직
        }
    }
    
    // CartTest.kt
    import org.junit.Test
    import org.mockito.Mockito.*
    import kotlin.test.assertEquals
    
    class CartTest {
        private val discountService: DiscountService = mock(DiscountService::class.java)
        private val cart = Cart(discountService)
    
        @Test
        fun testAddItem() {
            val item = Item("Sample Item", 100)
            cart.addItem(item)
            assertEquals(1, cart.items.size) // 아이템이 하나 추가되었는지 확인
        }
    
        @Test
        fun testApplyDiscount() {
            when(discountService.getDiscount("SUMMER21")).thenReturn(10)
            cart.applyDiscount("SUMMER21")
            // 할인 적용 로직 검증
        }
    }

    예제 2: API 호출

    API 호출이 필요한 서비스를 테스트할 때 Mockito를 사용할 수 있습니다.

    // UserService.kt
    class UserService(private val apiClient: ApiClient) {
        fun getUser(userId: String): User {
            return apiClient.fetchUser(userId)
        }
    }
    
    // UserServiceTest.kt
    import org.junit.Test
    import org.mockito.Mockito.*
    import kotlin.test.assertEquals
    
    class UserServiceTest {
        private val apiClient: ApiClient = mock(ApiClient::class.java)
        private val userService = UserService(apiClient)
    
        @Test
        fun testGetUser() {
            val user = User("John Doe")
            when(apiClient.fetchUser("1")).thenReturn(user)
            assertEquals("John Doe", userService.getUser("1").name) // 사용자 이름이 "John Doe"인지 확인
        }
    }

    5. 흔한 실수와 주의사항

  • 실수 1: Mockito로 목 객체를 생성할 때 mock()을 사용하지 않고 직접 인스턴스를 생성하는 것.
  • - 잘못된 코드:

        val discountService = DiscountService() // 잘못된 방식

    - 올바른 코드:

        val discountService: DiscountService = mock(DiscountService::class.java) // 올바른 방식
  • 실수 2: 테스트 메서드에 @Test 애너테이션을 붙이지 않아서 테스트가 실행되지 않는 것.
  • - 잘못된 코드:

        fun testAdd() { 
            // 테스트 코드 
        } // @Test가 없음

    - 올바른 코드:

        @Test
        fun testAdd() { 
            // 테스트 코드 
        }

    6. 정리

  • 단위 테스트는 코드의 품질을 보장하는 필수 요소입니다.
  • Mockito를 사용하면 외부 의존성을 쉽게 대체하여 테스트할 수 있습니다.
  • 테스트 작성 시 주의해야 할 점은 목 객체 생성 방법과 애너테이션을 잊지 않는 것입니다.

다음에 학습하면 좋은 주제는 통합 테스트와 테스트 주도 개발(TDD)입니다. 이들 주제를 통해 보다 깊이 있는 테스트 전략을 배울 수 있습니다.