0Pricing
Android Academy · Урок

Имитация объектов с Mockito

Изолируйте зависимости с помощью Mockito и MockK. Задавайте возвращаемые значения, проверяйте взаимодействия, перехватывайте аргументы и используйте шпионы для частичной имитации.

«Имитация объектов с Mockito» — бесплатный урок Android Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Android Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Android Academy содержит 4 уроков всего.

Что такое имитация?

Имитация — это фиктивный объект, который заменяет настоящую зависимость в тестах. В отличие от фиктивной реализации (рабочей реализации в памяти), имитация:

  • Автоматически создаётся библиотекой
  • Записывает, какие методы вызывались и с какими аргументами
  • Возвращает всё, что вы укажете (настройка заглушки)
  • Позволяет проверить взаимодействия после теста

Настройка Mockito

Добавьте Mockito и MockK (альтернативу, ориентированную на Kotlin) в app/build.gradle:

// 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; используйте mockito-kotlin или MockK, чтобы избежать неожиданных значений null

Имитация объектов и сопутствующих объектов

MockK может имитировать объекты Kotlin и сопутствующие объекты — это невозможно с 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)

Быстрая проверка

Каково назначение verify() в тесте Mockito или MockK?

Итоги: имитация с Mockito и MockK

Имитации позволяют изолировать и проверять поведение:

  • mock() / mockk() — создают имитацию интерфейса или класса
  • whenever(...).thenReturn(...) / every { } returns ... — настраивают возвращаемые значения
  • coEvery / coVerify — для приостанавливаемых функций Kotlin (MockK)
  • verify(mock).method(args) — проверяет вызов метода
  • ArgumentCaptor — захватывает и проверяет аргументы
  • spy() / spyk() — частично имитируют настоящий объект
  • Предпочитайте фиктивные реализации для данных, а имитации используйте для проверки поведения

Далее: тестирование интерфейса с помощью Espresso.

Часто задаваемые вопросы

Урок «Имитация объектов с Mockito» бесплатный?

Да — полный текст урока «Имитация объектов с Mockito» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Android Academy, подпишись на CoddyKit PRO. Курс Android Academy содержит 4 уроков всего.

Чему я научусь в уроке «Имитация объектов с Mockito»?

Изолируйте зависимости с помощью Mockito и MockK. Задавайте возвращаемые значения, проверяйте взаимодействия, перехватывайте аргументы и используйте шпионы для частичной имитации. Ты практикуешь Android Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Android Academy?

Предыдущий опыт не требуется. Android Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.

Сколько времени занимает урок «Имитация объектов с Mockito»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Android Academy?

Да. Каждый урок Android Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Модульное тестирование с JUnit
  2. Имитация объектов с Mockito
  3. Тестирование интерфейса с Espresso
  4. Отладка и профилирование
← Назад к Android Academy