Что такое Mock? - IlyaKovanov/lib GitHub Wiki
Mock (или "мок") — это заглушка, которая притворяется реальным объектом, но на самом деле это фейк, который мы полностью контролируем.
Простая аналогия
Представьте, что вы режиссер и снимаете сцену, где актер должен звонить по телефону.
Без мока: Вы даете актеру реальный телефон, звоните настоящему человеку и надеетесь, что он скажет нужные слова.
С моком: Вы даете актеру игрушечный телефон, а сами стоите за кадром и говорите нужные фразы. Вы полностью контролируете диалог!
Простой пример на PHP
Допустим, у нас есть класс, который отправляет email:
class EmailService {
public function sendEmail($to, $subject, $message) {
// Здесь реальная отправка email через SMTP
// Это долго и зависит от интернета
return mail($to, $subject, $message);
}
}
class UserRegistration {
private $emailService;
public function __construct(EmailService $emailService) {
$this->emailService = $emailService;
}
public function registerUser($email, $name) {
// Регистрируем пользователя...
// Отправляем приветственное письмо
$result = $this->emailService->sendEmail(
$email,
'Добро пожаловать!',
"Привет, $name!"
);
return $result;
}
}
Проблема при тестировании
Если мы тестируем UserRegistration, нам не нужно реально отправлять письма каждый раз! Это:
Медленно
Зависит от интернета
Засоряет почту
Ненадежно
Решение с Mock
// В тестах мы создаем мок EmailService
$emailServiceMock = $this->createMock(EmailService::class);
// Говорим моку: "Когда вызовут sendEmail с такими параметрами, верни true"
$emailServiceMock->method('sendEmail')
->with('[email protected]', 'Добро пожаловать!', 'Привет, Иван!')
->willReturn(true);
// Теперь тестируем наш основной класс
$registration = new UserRegistration($emailServiceMock);
$result = $registration->registerUser('[email protected]', 'Иван');
// Проверяем, что все работает
$this->assertTrue($result);
Что мы получили с Mock:
Скорость — не ждем реальную отправку email
Изоляция — тестируем только логику регистрации, а не отправку писем
Контроль — можем симулировать любые сценарии (успех, ошибка)
Предсказуемость — всегда знаем, что вернет мок
Основные способы использования Mock:
Замена медленных операций
// Вместо реальной базы данных
$dbMock = $this->createMock(Database::class);
$dbMock->method('query')->willReturn(['user' => 'Ivan']);
Симуляция ошибок
// Проверяем, как система реагирует на ошибки
$emailServiceMock->method('sendEmail')
->willThrowException(new \Exception('SMTP error'));
Проверка вызовов
// Убеждаемся, что метод был вызван
$emailServiceMock->expects($this->once())
->method('sendEmail');
Возврат разных значений
// Первый вызов вернет true, второй - false
$emailServiceMock->method('sendEmail')
->will($this->onConsecutiveCalls(true, false));