Имитация объектов с 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 callverify() — проверка взаимодействий
Используйте 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 — локальная установка не требуется.
Все уроки этого курса
- Модульное тестирование с JUnit
- Имитация объектов с Mockito
- Тестирование интерфейса с Espresso
- Отладка и профилирование