Мокирование — это мощный инструмент для изоляции тестируемого кода от его зависимостей. В Laravel и PHPUnit вы можете мокать практически всё, что угодно: фасады, модели, репозитории, сервисы, HTTP-клиенты и даже глобальные функции. Давайте разберем, что и как можно мокать.
Фасады Laravel (например, DB
, Cache
, Config
, Storage
) легко мокать с помощью shouldReceive
.
Пример:
use Illuminate\Support\Facades\DB;
DB::shouldReceive('select')
->once()
->withAnyArgs()
->andReturn([
(object) ['UF_PROJECT' => 384, 'RATING' => '5.25']
]);
Модели Eloquent можно мокать, чтобы имитировать их поведение. Например, вы можете мокать методы where
, find
, create
и другие.
Пример:
use App\Models\User;
use Mockery;
$userMock = Mockery::mock(User::class);
$userMock->shouldReceive('find')
->once()
->with(1)
->andReturn((object) ['id' => 1, 'name' => 'John Doe']);
// Теперь $userMock будет возвращать фиктивные данные при вызове find(1)
Если вы используете репозитории для работы с данными, их также можно мокать. Это особенно полезно, если вы хотите изолировать тест от базы данных.
Пример:
use App\Repositories\UserRepository;
use Mockery;
$repositoryMock = Mockery::mock(UserRepository::class);
$repositoryMock->shouldReceive('getUserById')
->once()
->with(1)
->andReturn((object) ['id' => 1, 'name' => 'John Doe']);
// Теперь $repositoryMock будет возвращать фиктивные данные при вызове getUserById(1)
Сервисы, которые зависят от других сервисов или репозиториев, также можно мокать.
Пример:
use App\Services\UserService;
use Mockery;
$userServiceMock = Mockery::mock(UserService::class);
$userServiceMock->shouldReceive('getUserDetails')
->once()
->with(1)
->andReturn(['id' => 1, 'name' => 'John Doe']);
// Теперь $userServiceMock будет возвращать фиктивные данные при вызове getUserDetails(1)
Если ваш код делает HTTP-запросы (например, через Guzzle или Laravel HTTP-клиент), вы можете мокать эти запросы.
Пример:
use Illuminate\Support\Facades\Http;
Http::fake([
'api.example.com/users/1' => Http::response(['id' => 1, 'name' => 'John Doe'], 200),
]);
// Теперь все запросы к api.example.com/users/1 будут возвращать фиктивные данные
Если ваш код использует глобальные функции (например, time()
, file_get_contents
), их также можно мокать с помощью библиотеки Mockery
.
Пример:
use Mockery;
Mockery::mock('alias:time')->andReturn(1234567890);
// Теперь time() всегда будет возвращать 1234567890
Если ваш код отправляет события, вы можете мокать их, чтобы проверить, что они были отправлены.
Пример:
use Illuminate\Support\Facades\Event;
Event::fake();
// Ваш код, который отправляет событие
event(new UserRegistered($user));
// Проверяем, что событие было отправлено
Event::assertDispatched(UserRegistered::class);
Если ваш код отправляет уведомления, вы можете мокать их, чтобы проверить, что они были отправлены.
Пример:
use Illuminate\Support\Facades\Notification;
Notification::fake();
// Ваш код, который отправляет уведомление
$user->notify(new WelcomeNotification);
// Проверяем, что уведомление было отправлено
Notification::assertSentTo($user, WelcomeNotification::class);
Если ваш код добавляет задачи в очередь, вы можете мокать их, чтобы проверить, что они были добавлены.
Пример:
use Illuminate\Support\Facades\Queue;
Queue::fake();
// Ваш код, который добавляет задачу в очередь
dispatch(new ProcessPodcast($podcast));
// Проверяем, что задача была добавлена в очередь
Queue::assertPushed(ProcessPodcast::class);
Если ваш код отправляет письма, вы можете мокать их, чтобы проверить, что они были отправлены.
Пример:
use Illuminate\Support\Facades\Mail;
Mail::fake();
// Ваш код, который отправляет письмо
Mail::to('user@example.com')->send(new WelcomeMail);
// Проверяем, что письмо было отправлено
Mail::assertSent(WelcomeMail::class);
Mockery
Mockery
— это мощная библиотека для создания мок-объектов. Она интегрирована с PHPUnit и Laravel.
Пример:
use Mockery;
$mock = Mockery::mock(ClassName::class);
$mock->shouldReceive('methodName')
->once()
->with('arg1', 'arg2')
->andReturn('result');
Фасады Laravel можно мокать с помощью shouldReceive
.
Пример:
use Illuminate\Support\Facades\DB;
DB::shouldReceive('select')
->once()
->withAnyArgs()
->andReturn([/* фиктивные данные */]);
PHPUnit
PHPUnit также предоставляет встроенные методы для создания мок-объектов.
Пример:
$mock = $this->createMock(ClassName::class);
$mock->method('methodName')
->willReturn('result');
Вы можете мокать практически всё, что угодно: фасады, модели, репозитории, сервисы, HTTP-клиенты, глобальные функции, события, уведомления, очереди и почту. Это делает ваши тесты более гибкими и изолированными от внешних зависимостей.
Теперь вы знаете, как мокать различные части вашего приложения! 🚀