
Тестирование кода, особенно в сложных системах, зачастую затруднено из-за зависимости от реальных баз данных, внешних сервисов или действий пользователей. Чтобы упростить тестирование, используют заглушки — это упрощенные версии реальных компонентов, которые помогают проверить работу системы без необходимости запускать всё "по-настоящему".
Моки (Mocks), стабы (Stubs) и фейки (Fakes) — это разновидности заглушек, которые заменяют реальные компоненты системы в тестировании. Разница между ними заключается в том, насколько они реалистичны и что именно позволяют протестировать.
Стаб (Stub) — это простая заглушка, которая возвращает заранее определенные ответы, но не содержит логики или сложного поведения.
Фейк (Fake) — это более сложная замена реальной зависимости, которая частично имитирует ее поведение. В отличие от стаба, фейк может содержать простую реализацию логики.
Мок (Mock) — это объект, который не только подменяет реальный компонент, но и позволяет проверять, как с ним взаимодействовали (сколько раз вызвали, с какими параметрами и т. д.).
Очень сложные определения, поэтому для начала давайте отдалимся от IT и рассмотрим пример из жизни.
Представьте, что вы открыли кофейню и хотите протестировать процесс приема заказов. Но есть проблема: у вас пока нет настоящего баристы, который готовит кофе. Как проверить, что кассир правильно принимает заказы?

Стаб (Stub) – Заглушка
Вы нанимаете стажера, который просто говорит:
"Ваш заказ принят! Кофе будет готов через 5 минут."
Он всегда отвечает одно и то же, но на самом деле кофе никто не готовит. Вы проверяете, что кассир умеет правильно оформлять заказ, но не тестируете сам процесс приготовления.
Когда использовать?
Если достаточно проверить, что заказ принимается, а готовка не важна.

Фейк (Fake) – Упрощенный аналог
Вы ставите в кофейне автомат для кофе, который реально готовит напитки, но выбор ограничен (только эспрессо и американо, без капучино и латте).
Теперь процесс ближе к реальности, но без полного функционала.
Когда использовать?
Когда нужно проверить весь процесс работы, но можно обойтись упрощенной версией.

Мок (Mock) – Проверка взаимодействий
Вы нанимаете человека, который не делает кофе, а просто записывает, какие заказы принимаются и как часто. В конце дня он показывает вам:
"10 человек заказали капучино"
"5 человек хотели сахар, но кассир забыл добавить"
Здесь вам важно не сам кофе протестировать, а проверить, что кассир правильно взаимодействует с клиентами.
Когда использовать?
Когда важно убедиться, что нужные действия происходят (например, API-запрос отправлен, метод вызван).
А теперь рассмотрим детальнее.
Стаб (Stub) — Заглушка
Когда стоит использовать?
Если нужно подменить реальный сервис фиксированными данными.
Когда достаточно просто вернуть заранее подготовленный ответ без сложных вычислений.
Пример:
В этом примере тестируется процесс оплаты. Вместо реального платежного шлюза (который может быть недоступен или работать медленно) используется стаб, который всегда возвращает успешный результат.
class OrderService(private val paymentGateway: PaymentGateway) {
fun processOrder(amount: Double): String {
return if (paymentGateway.charge(amount)) "Payment Successful" else "Payment Failed"
}
}
// Стаб-заглушка
class StubPaymentGateway : PaymentGateway {
override fun charge(amount: Double): Boolean {
return true // Всегда возвращает успешный платеж
}
}
// Тест
class OrderServiceTest {
@Test
fun `should process order successfully with stub payment gateway`() {
val stubGateway = StubPaymentGateway()
val orderService = OrderService(stubGateway)
val result = orderService.processOrder(100.0)
assertEquals("Payment Successful", result)
}
}
💡 Стабы не проверяют, как система взаимодействует с ними, они просто выдают данные.
Фейк (Fake) — Упрощенный аналог
Когда стоит использовать?
Когда нужен легковесный аналог реального компонента, который ведет себя похоже, но проще.
В тестах, где важно не просто получить статические данные, а динамически их изменять.
Пример:
Здесь тестируется регистрация пользователя. Вместо реальной базы данных используется фейковая версия, которая хранит данные в памяти. Это позволяет тестировать без подключения к настоящему хранилищу.
class FakeDatabase : UserRepository {
private val users = mutableListOf<User>()
override fun save(user: User) {
users.add(user)
}
override fun findByEmail(email: String): User? {
return users.find { it.email == email }
}
}
// Тест с фейковым репозиторием
class UserServiceTest {
@Test
fun `should store and retrieve user with fake database`() {
val fakeDb = FakeDatabase()
val userService = UserService(fakeDb)
val user = User("John Doe", "john@example.com")
userService.register(user)
val retrievedUser = fakeDb.findByEmail("john@example.com")
assertEquals(user, retrievedUser)
}
}
💡 Фейки могут вести себя как настоящие компоненты, но обычно упрощены и не требуют внешних зависимостей (например, реального сервера или БД).
Мок (Mock) — Подделка с проверкой взаимодействий
Когда стоит использовать?
Когда важно проверить, как система взаимодействует с зависимостью (например, какие методы вызываются и с какими параметрами).
Если нужно протестировать бизнес-логику без реального сервиса, но с контролем вызовов.
Пример:
Здесь тестируется, был ли вызван метод оплаты при оформлении заказа. Используется мок, который позволяет не только подставлять данные, но и проверять, вызывались ли определенные методы с нужными параметрами.
class OrderService(private val paymentGateway: PaymentGateway) {
fun processOrder(amount: Double): String {
return if (paymentGateway.charge(amount)) "Payment Successful" else "Payment Failed"
}
}
// Тест с мок-объектом
class OrderServiceMockTest {
@Test
fun `should call payment gateway when processing order`() {
val mockGateway = mock<PaymentGateway>()
whenever(mockGateway.charge(any())).thenReturn(true)
val orderService = OrderService(mockGateway)
orderService.processOrder(50.0)
verify(mockGateway).charge(50.0) // Проверяем, что метод вызван с нужным значением
}
}
💡 Моки полезны, когда важно убедиться, что тестируемый код корректно взаимодействует с зависимостью, а не только получить фиксированные данные.
Резюме
Заглушки — мощный инструмент, который помогает тестировать системы быстрее и эффективнее. Использование стабов, фейков и моков позволяет изолировать тестируемый код от внешних зависимостей, делая тесты надежными и предсказуемыми. Главное — правильно выбирать подходящий тип заглушки в зависимости от целей тестирования, чтобы находить проблемы на ранних этапах и повышать качество продукта.
А больше интересного можно найти в телеграм канале «Тестировщики нужны».