학습
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. 흔한 실수와 주의사항
mock()을 사용하지 않고 직접 인스턴스를 생성하는 것.- 잘못된 코드:
val discountService = DiscountService() // 잘못된 방식
- 올바른 코드:
val discountService: DiscountService = mock(DiscountService::class.java) // 올바른 방식
@Test 애너테이션을 붙이지 않아서 테스트가 실행되지 않는 것.- 잘못된 코드:
fun testAdd() {
// 테스트 코드
} // @Test가 없음
- 올바른 코드:
@Test
fun testAdd() {
// 테스트 코드
}
6. 정리
다음에 학습하면 좋은 주제는 통합 테스트와 테스트 주도 개발(TDD)입니다. 이들 주제를 통해 보다 깊이 있는 테스트 전략을 배울 수 있습니다.