0Pricing
Android Academy · 강의

Mockito를 사용한 모의 객체

Mockito와 MockK로 의존성을 격리합니다. 반환 값을 스텁하고 상호 작용을 검증하며 인수를 캡처하고 부분 모의 객체에는 스파이를 사용합니다.

Mockito를 사용한 모의 객체은(는) CoddyKit의 무료 Android Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Android Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Android Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

모킹이란 무엇인가요?

모의 객체는 테스트에서 실제 의존성을 대체하는 가짜 객체입니다. 실제로 동작하는 메모리 내 구현인 가짜 객체와 달리 모의 객체는 다음과 같은 특징이 있습니다:

  • 라이브러리가 자동으로 생성합니다
  • 어떤 메서드가 어떤 인수와 함께 호출되었는지 기록합니다
  • 지정한 값을 반환합니다(스텁 설정)
  • 테스트 후 상호작용을 검증할 수 있게 합니다

Mockito 설정

app/build.gradle에 Mockito와 MockK(Kotlin 중심 대안)를 추가합니다:

// app/build.gradle:
testImplementation 'org.mockito:mockito-core:5.10.0'
testImplementation 'org.mockito.kotlin:mockito-kotlin:5.2.1'

// MockK (Kotlin-idiomatic alternative to Mockito):
testImplementation 'io.mockk:mockk:1.13.10'

모의 객체 만들기

mock() 또는 @Mock 주석을 사용해 모의 객체를 만듭니다:

import org.mockito.kotlin.*

interface UserApi {
    suspend fun fetchUsers(): List<User>
    suspend fun deleteUser(id: Int)
}

class RepositoryTest {

    // Option 1: create inline
    private val api: UserApi = mock()

    // Option 2: use annotation + MockitoJUnit4Runner
    @Mock lateinit var api2: UserApi

    @get:Rule
    val mockitoRule = MockitoJUnit.rule()
}

스텁 설정 — 반환 값 정의하기

whenever(mock.method()).thenReturn(value)을 사용해 모의 객체가 반환할 값을 설정합니다:

val api: UserApi = mock()

// Stub a return value:
whenever(api.fetchUsers()).thenReturn(
    listOf(User(1, "Alice"), User(2, "Bob"))
)

// Stub an exception:
whenever(api.fetchUsers()).thenThrow(RuntimeException("Network error"))

// Return different values on consecutive calls:
whenever(api.fetchUsers())
    .thenReturn(emptyList())           // first call
    .thenReturn(listOf(User(1, "Alice"))) // second call

verify() — 상호작용 확인하기

verify()를 사용해 메서드가 호출되었는지와 몇 번 호출되었는지를 검증합니다:

val api: UserApi = mock()
val repo = UserRepository(api)

repo.refreshUsers()

// Verify that fetchUsers() was called exactly once:
verify(api).fetchUsers()

// Verify called with specific argument:
repo.deleteUser(42)
verify(api).deleteUser(42)

// Verify called exactly 3 times:
verify(api, times(3)).fetchUsers()

// Verify never called:
verify(api, never()).deleteUser(any())

ArgumentCaptor

ArgumentCaptor는 모의 객체 메서드에 전달된 인수를 캡처하여 그 값을 검증할 수 있게 합니다:

val api: UserApi = mock()
val captor = argumentCaptor<User>()

val repo = UserRepository(api)
repo.saveUser(User(1, "Alice"))

verify(api).saveUser(captor.capture())

val captured = captor.firstValue
assertEquals(1, captured.id)
assertEquals("Alice", captured.name)

MockK — Kotlin 중심 모킹

MockK는 Kotlin을 위해 설계되었으며 확장 함수, 코루틴, 객체를 기본적으로 처리합니다:

import io.mockk.*

val api = mockk<UserApi>()

// Stub:
every { api.fetchUsers() } returns listOf(User(1, "Alice"))

// Stub suspend function:
coEvery { api.fetchUsers() } returns listOf(User(1, "Alice"))

// Verify:
val repo = UserRepository(api)
runBlocking { repo.refresh() }
coVerify { api.fetchUsers() }

MockK로 코루틴 모킹하기

일시 중단 함수에는 coEvery와 coVerify를 사용하세요:

val api = mockk<UserApi>()

// Stub suspend function:
coEvery { api.fetchUsers() } returns listOf(User(1, "Alice"))
coEvery { api.deleteUser(any()) } just Runs  // returns Unit

// Test:
runTest {
    val repo = UserRepository(api)
    repo.refresh()
    coVerify(exactly = 1) { api.fetchUsers() }
    coVerify(exactly = 0) { api.deleteUser(any()) }
}

스파이 — 부분 모킹

spy는 실제 객체를 감쌉니다. 재정의하지 않는 한 실제 메서드가 기본적으로 호출됩니다:

// Mockito Spy:
val realList = mutableListOf("a", "b", "c")
val spyList = spy(realList)

// Real method called:
spyList.add("d")
assertEquals(4, spyList.size)   // real add() was called

// Override specific method:
doReturn(99).`when`(spyList).size
assertEquals(99, spyList.size)  // overridden

// MockK Spy:
val spyObj = spyk(RealService())
every { spyObj.expensiveCall() } returns "fake result"

모의 객체와 가짜 객체는 언제 사용하나요?

실용적인 지침입니다:

  • 가짜 객체 사용: 동작하는 메모리 내 구현(DAO, 저장소)이 필요할 때 — 읽기 쉽고 라이브러리가 필요하지 않습니다
  • 모의 객체 사용: 특정 인수와 함께 특정 메서드가 호출되었는지 검증해야 할 때(분석 이벤트, API 호출)
  • 과도한 모킹 피하기: 모든 것을 모킹하면 테스트 대상 로직이 아니라 모의 객체를 검증하게 됩니다

일반적인 실수

모킹할 때 피해야 할 문제입니다:

  • 값 객체 모킹 — 데이터 클래스가 아니라 인터페이스나 추상화를 모킹하세요
  • 너무 깊게 모킹하기 — 하나의 테스트에 모의 객체가 5개 필요하다면 코드가 지나치게 결합된 것입니다
  • 상호작용이 중요한데도 검증하지 않기 — 스텁 설정만 하지 말고 검증도 하세요
  • Mockito와 Kotlin 기본값 — Kotlin 매개변수는 기본적으로 null을 허용하지 않습니다. 예기치 않은 null 문제를 피하려면 mockito-kotlin 또는 MockK를 사용하세요

객체와 Companion 객체 모킹하기

MockK는 Kotlin 객체와 Companion 객체를 모킹할 수 있으며, 이는 Mockito로는 불가능합니다:

object DateProvider {
    fun today(): String = "2024-01-01"
}

// In test:
mockkObject(DateProvider)
every { DateProvider.today() } returns "2099-12-31"

val result = DateProvider.today()
assertEquals("2099-12-31", result)

// Restore after test:
unmockkObject(DateProvider)

빠른 확인

Mockito 또는 MockK 테스트에서 verify()의 목적은 무엇인가요?

복습: Mockito와 MockK 모킹

모의 객체를 사용하면 동작을 격리하고 검증할 수 있습니다:

  • mock() / mockk() — 인터페이스나 클래스에서 모의 객체를 만듭니다
  • whenever(...).thenReturn(...) / every { } returns ... — 반환 값을 스텁으로 설정합니다
  • coEvery / coVerify — Kotlin 일시 중단 함수에 사용합니다(MockK)
  • verify(mock).method(args) — 메서드가 호출되었는지 검증합니다
  • ArgumentCaptor — 인수를 캡처하고 검사합니다
  • spy() / spyk() — 실제 객체를 부분적으로 모킹합니다
  • 데이터에는 가짜 객체를 우선 사용하고, 동작 검증에는 모의 객체를 사용하세요

다음: Espresso를 사용한 UI 테스트입니다.

자주 묻는 질문

“Mockito를 사용한 모의 객체” 강의는 무료인가요?

네 — “Mockito를 사용한 모의 객체” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Android Academy 강의 전체를 잠금 해제할 수 있습니다. Android Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“Mockito를 사용한 모의 객체”에서 뭘 배우나요?

Mockito와 MockK로 의존성을 격리합니다. 반환 값을 스텁하고 상호 작용을 검증하며 인수를 캡처하고 부분 모의 객체에는 스파이를 사용합니다. 브라우저에서 직접 실행하는 실습 코드로 Android Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Android Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Android Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.

“Mockito를 사용한 모의 객체” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Android Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Android Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. JUnit을 사용한 단위 테스트
  2. Mockito를 사용한 모의 객체
  3. Espresso를 사용한 UI 테스트
  4. 디버깅과 프로파일링
← Android Academy(으)로 돌아가기