PHpullh
학습 라이브러리/Kotlin/스텁/목/스파이 비교

KOTLIN · 테스트

스텁/목/스파이 비교

테스트 더블의 세 가지 유형을 비교합니다. 각각의 사용 목적과 적합한 상황을 실습합니다.

테스트중급stubmockspytest-double-comparison

핵심 설명

테스트 더블의 세 가지 유형을 비교합니다. 각각의 사용 목적과 적합한 상황을 실습합니다.

Kotlin code

interface PaymentGateway {
    fun charge(amount: Int): Boolean
    fun refund(amount: Int): Boolean
    fun getBalance(): Int
}

// Stub: 고정된 결과 반환 (상태 검증용)
class StubGateway(private val chargeResult: Boolean = true) : PaymentGateway {
    override fun charge(amount: Int) = chargeResult
    override fun refund(amount: Int) = true
    override fun getBalance() = 100000
}

// Mock: 호출 기록 + 검증 (행위 검증용)
class MockGateway : PaymentGateway {
    val charges = mutableListOf<Int>()
    val refunds = mutableListOf<Int>()
    override fun charge(amount: Int): Boolean { charges.add(amount); return true }
    override fun refund(amount: Int): Boolean { refunds.add(amount); return true }
    override fun getBalance() = 0
}

// Spy: 실제 동작 + 기록 (부분 모킹)
class SpyGateway(private val real: PaymentGateway) : PaymentGateway {
    val callLog = mutableListOf<String>()
    override fun charge(amount: Int): Boolean {
        callLog.add("charge($amount)")
        return real.charge(amount) // 실제 호출
    }
    override fun refund(amount: Int): Boolean {
        callLog.add("refund($amount)")
        return real.refund(amount)
    }
    override fun getBalance(): Int { callLog.add("getBalance()"); return real.getBalance() }
}

fun main() {
    // Stub: "결제 성공 시 주문이 생성되는가?"
    val stub = StubGateway(chargeResult = true)
    assert(stub.charge(5000)) { "결제 실패" }
    println("✓ Stub: 결제 성공 시나리오")

    // Mock: "정확한 금액으로 결제가 호출되었는가?"
    val mock = MockGateway()
    mock.charge(15000)
    assert(mock.charges == listOf(15000)) { "호출 검증 실패" }
    println("✓ Mock: 결제 금액 검증")

    // Spy: "실제 동작 + 호출 기록"
    val spy = SpyGateway(StubGateway())
    spy.charge(3000)
    spy.getBalance()
    println("✓ Spy 호출 로그: ${spy.callLog}")
}

학습 팁

Stub은 "무엇을 반환하는가", Mock은 "무엇이 호출되었는가", Spy는 "실제 동작 + 기록"으로 구분하세요.

주의할 점

Mock과 Stub을 혼용하면 테스트 의도가 불명확해집니다. 하나의 테스트에서는 하나의 더블 유형에 집중하세요.

자주 묻는 질문

스텁/목/스파이 비교란 무엇인가요?

테스트 더블의 세 가지 유형을 비교합니다. 각각의 사용 목적과 적합한 상황을 실습합니다.

스텁/목/스파이 비교 학습 시 주의할 점은 무엇인가요?

Mock과 Stub을 혼용하면 테스트 의도가 불명확해집니다. 하나의 테스트에서는 하나의 더블 유형에 집중하세요.