
Тестирование кода, особенно в сложных системах, зачастую затруднено из-за зависимости от реальных баз данных, внешних сервисов или действий пользователей. Чтобы упростить тестирование, используют заглушки — это упрощенные версии реальных компонентов, которые помогают проверить работу системы без необходимости запускать всё «по-настоящему».
Моки (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) // Проверяем, что метод вызван с нужным значением } }
💡 Моки полезны, когда важно убедиться, что тестируемый код корректно взаимодействует с зависимостью, а не только получить фиксированные данные.
Резюме
Заглушки — мощный инструмент, который помогает тестировать системы быстрее и эффективнее. Использование стабов, фейков и моков позволяет изолировать тестируемый код от внешних зависимостей, делая тесты надежными и предсказуемыми. Главное — правильно выбирать подходящий тип заглушки в зависимости от целей тестирования, чтобы находить проблемы на ранних этапах и повышать качество продукта.
А больше интересного можно найти в телеграм канале «Тестировщики нужны».
ссылка на оригинал статьи https://habr.com/ru/articles/899788/
Добавить комментарий