Комментарии (1)
🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое мок-объекты (мокинг) в тестировании?
Мок-объект (mock object) — это специальный объект-заглушка, который имитирует поведение реальной зависимости в автоматизированных тестах (обычно модульных). Он позволяет изолировать тестируемый код от внешних систем, таких как базы данных, API, файловая система или сложные сервисы, заменяя их контролируемыми "двойниками".
Зачем нужно мокинг?
Основные цели:
- Изоляция теста: Тест проверяет только логику конкретного класса/метода, не завися от работы внешних сервисов.
- Контроль поведения: Можно легко задать нужные возвращаемые значения, имитировать исключения или задержки.
- Проверка взаимодействий: Можно убедиться, что тестируемый код корректно вызывает методы зависимостей с ожидаемыми аргументами.
- Ускорение тестов: Исключаются медленные операции (сеть, дисковый ввод-вывод, сложные вычисления).
Пример в PHP (с использованием PHPUnit и Mockery)
Допустим, у нас есть сервис PaymentService, который зависит от PaymentGateway:
// Реальный класс, который мы хотим протестировать
class PaymentService {
private $gateway;
public function __construct(PaymentGateway $gateway) {
$this->gateway = $gateway;
}
public function processPayment(float $amount, string $token): bool {
if ($amount <= 0) {
throw new InvalidArgumentException('Amount must be positive');
}
$result = $this->gateway->charge($token, $amount);
if (!$result) {
$this->gateway->logFailedTransaction($token, $amount);
return false;
}
return true;
}
}
// Тест с использованием мок-объекта
use PHPUnit\Framework\TestCase;
use Mockery;
class PaymentServiceTest extends TestCase {
public function testProcessPaymentSuccess() {
// 1. Создаем мок-объект для PaymentGateway
$gatewayMock = Mockery::mock(PaymentGateway::class);
// 2. Настраиваем ожидания:
// - Метод charge будет вызван 1 раз с конкретными параметрами
// - Вернет true (успешная оплата)
$gatewayMock->shouldReceive('charge')
->once()
->with('test_token_123', 100.0)
->andReturn(true);
// 3. Метод logFailedTransaction НЕ должен вызываться
$gatewayMock->shouldNotReceive('logFailedTransaction');
// 4. Создаем тестируемый объект, передавая мок
$service = new PaymentService($gatewayMock);
// 5. Выполняем тестируемый метод
$result = $service->processPayment(100.0, 'test_token_123');
// 6. Проверяем результат
$this->assertTrue($result);
// 7. Проверяем, что все ожидания от мока выполнены
Mockery::close();
}
public function testProcessPaymentFailure() {
$gatewayMock = Mockery::mock(PaymentGateway::class);
// Настраиваем мок так, чтобы charge вернул false (ошибка оплаты)
$gatewayMock->shouldReceive('charge')
->once()
->with('test_token_456', 50.0)
->andReturn(false);
// Ожидаем, что будет вызван метод логирования
$gatewayMock->shouldReceive('logFailedTransaction')
->once()
->with('test_token_456', 50.0);
$service = new PaymentService($gatewayMock);
$result = $service->processPayment(50.0, 'test_token_456');
$this->assertFalse($result);
Mockery::close();
}
}
Типы тестовых двойников (Test Doubles)
Моки — частный случай более общей концепции. Различают:
- Стабы (Stubs) — предоставляют предопределенные ответы на вызовы методов, но не проверяют взаимодействия.
- Моки (Mocks) — как в примере выше: задают ожидания к взаимодействию и проверяют их выполнение.
- Фейки (Fakes) — упрощенные рабочие реализации (например, репозиторий в памяти вместо обращения к БД).
- Спаи (Spies) — записывают вызовы для последующей проверки, но не задают ожидания заранее.
Ключевые принципы мокинга в PHP
- Мокируйте только зависимости — не следует мокировать класс, который вы тестируете.
- Используйте инъекцию зависимостей — это упрощает замену реальных объектов моками.
- Избегайте чрезмерного мокинга — если мокируете слишком много, возможно, нарушены принципы SOLID.
- Выбирайте подходящий инструмент:
* **PHPUnit** — встроенные моки (`createMock()`, `createConfiguredMock()`)
* **Mockery** — более выразительный синтаксис (как в примере)
* **Prophecy** — часто используется в Symfony-экосистеме
Распространенные сценарии использования
- Тестирование сервисов с внешними API (платежи, почта, SMS)
- Работа с базой данных — мок репозитория
- Тестирование событий (events) и подписчиков
- Имитация исключительных ситуаций (таймауты, ошибки сети)
Мокинг — это незаменимый инструмент для создания быстрых, стабильных и изолированных модульных тестов, который позволяет сосредоточиться на бизнес-логике, не беспокоясь о внешних факторах.