# Тестування Laravel у 2026: Pest, Mocking та питання технічних співбесід > Повний посібник з тестування Laravel-застосунків за допомогою Pest у 2026 році. Розглядаються Feature та Unit тести, мокінг фасадів, архітектурні тести, мутаційне тестування та типові питання технічних співбесід. - Published: 2026-06-04 - Updated: 2026-06-04 - Author: SharpSkill - Tags: laravel, testing, pest, php, interview - Reading time: 8 min --- Тестування є невід'ємною частиною професійної розробки на Laravel. У 2026 році екосистема PHP досягла нового рівня зрілості, а фреймворк Pest став стандартом де-факто для написання тестів у Laravel-проєктах. Сучасні команди розробників очікують від кандидатів глибокого розуміння тестових практик, адже якість коду безпосередньо впливає на стабільність продукту та швидкість впровадження нових функцій. Ця стаття охоплює ключові аспекти тестування Laravel-застосунків: від базової конфігурації Pest до просунутих технік мокінгу зовнішніх сервісів. Особлива увага приділяється архітектурним тестам та мутаційному тестуванню — інструментам, які допомагають забезпечити високу якість тестового покриття. Наприкінці наведено типові питання технічних співбесід, що дозволить підготуватися до інтерв'ю на позиції Laravel-розробника. Матеріал розрахований на розробників із базовим досвідом роботи з Laravel, які прагнуть поглибити свої знання у сфері тестування та підготуватися до технічних співбесід у провідних IT-компаніях. > **Чому Pest, а не PHPUnit?** > > Pest побудований на основі PHPUnit, але пропонує значно лаконічніший синтаксис завдяки функціональному підходу. Замість створення класів та методів розробники описують тести за допомогою функцій `it()` та `test()`. Це скорочує обсяг boilerplate-коду на 40-60% порівняно з класичним PHPUnit. Крім того, Pest надає вбудовану підтримку архітектурних тестів, паралельного виконання та мутаційного тестування — функцій, які потребують додаткових плагінів у PHPUnit. ## Налаштування Pest у Laravel-проєкті Конфігурація Pest виконується через файл `tests/Pest.php`, де визначаються базові налаштування для різних типів тестів. Трейт `RefreshDatabase` автоматично скидає базу даних перед кожним Feature-тестом, забезпечуючи ізоляцію тестових сценаріїв. ```php // tests/Pest.php use Illuminate\Foundation\Testing\RefreshDatabase; pest() ->extend(Tests\TestCase::class) ->use(RefreshDatabase::class) ->in('Feature'); ``` Метод `extend()` вказує базовий клас для тестів, а `use()` додає необхідні трейти. Директива `in('Feature')` обмежує застосування цих налаштувань лише до Feature-тестів, залишаючи Unit-тести максимально швидкими без звернення до бази даних. ## Feature-тести: валідація HTTP-ендпоінтів Feature-тести перевіряють роботу застосунку на рівні HTTP-запитів, імітуючи реальну взаємодію користувачів із системою. Такі тести охоплюють повний цикл обробки запиту: маршрутизацію, валідацію, бізнес-логіку та формування відповіді. ```php // tests/Feature/UserRegistrationTest.php use App\Models\User; it('registers a new user with valid data', function () { $response = $this->postJson('/api/register', [ 'name' => 'Jane Doe', 'email' => 'jane@example.com', 'password' => 'SecurePass123!', 'password_confirmation' => 'SecurePass123!', ]); $response->assertStatus(201) ->assertJsonStructure(['user' => ['id', 'name', 'email']]); expect(User::where('email', 'jane@example.com')->exists())->toBeTrue(); }); ``` Тест демонструє комплексну перевірку процесу реєстрації: HTTP-статус відповіді, структуру JSON та фактичне створення запису в базі даних. Функція `expect()` з бібліотеки Expectation API забезпечує читабельний синтаксис для assertions. ## Unit-тести з Pest: ізольована бізнес-логіка Unit-тести фокусуються на окремих класах та методах, перевіряючи їхню поведінку в ізоляції від решти системи. Блок `describe()` групує пов'язані тести, створюючи логічну структуру тестового файлу. ```php // tests/Unit/PriceCalculatorTest.php use App\Services\PriceCalculator; describe('PriceCalculator', function () { it('applies a percentage discount correctly', function () { $calculator = new PriceCalculator(); // 20% off a 150.00 base price $result = $calculator->applyDiscount(150.00, 20); expect($result)->toBe(120.00); }); it('rejects negative discount values', function () { $calculator = new PriceCalculator(); expect(fn () => $calculator->applyDiscount(100.00, -5)) ->toThrow(InvalidArgumentException::class); }); }); ``` Перший тест перевіряє коректність обчислення знижки, другий — правильну обробку некоректних вхідних даних. Метод `toThrow()` дозволяє елегантно тестувати винятки без використання анотацій чи блоків try-catch. ## Мокінг фасадів Laravel: Mail, Queue, Notifications Laravel надає вбудовані механізми для мокінгу фасадів, що дозволяє тестувати відправку листів, постановку задач у чергу та надсилання сповіщень без реального виконання цих операцій. ```php // tests/Feature/OrderProcessingTest.php use App\Models\Order; use App\Models\User; use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Queue; use App\Mail\OrderConfirmation; use App\Jobs\ProcessPayment; it('dispatches payment job and sends confirmation email', function () { // Fake both Mail and Queue facades Mail::fake(); Queue::fake(); $user = User::factory()->create(); $order = Order::factory()->for($user)->create([ 'total' => 99.99, 'status' => 'pending', ]); // Act: confirm the order via HTTP $this->actingAs($user) ->postJson("/api/orders/{$order->id}/confirm") ->assertOk(); // Assert: payment job was dispatched with correct amount Queue::assertPushed(ProcessPayment::class, function ($job) use ($order) { return $job->order->id === $order->id && $job->order->total === 99.99; }); // Assert: confirmation email was sent to the user Mail::assertSent(OrderConfirmation::class, function ($mail) use ($user) { return $mail->hasTo($user->email); }); }); ``` Методи `Mail::fake()` та `Queue::fake()` перехоплюють виклики відповідних фасадів, дозволяючи перевірити, які листи мали бути відправлені та які задачі поставлені в чергу. Callback-функції в методах `assertPushed()` та `assertSent()` забезпечують детальну перевірку параметрів. ## Просунутий мокінг з Mockery: зовнішні сервіси Для мокінгу власних сервісів та зовнішніх API використовується бібліотека Mockery, яка інтегрована в Pest. Мок-об'єкти дозволяють контролювати поведінку залежностей та перевіряти правильність їхнього виклику. ```php // tests/Feature/PaymentGatewayTest.php use App\Services\PaymentGateway; use App\Services\StripeClient; it('charges the customer through the payment gateway', function () { // Create a mock of the Stripe client $stripeClient = Mockery::mock(StripeClient::class); $stripeClient->shouldReceive('charge') ->once() ->with('cus_abc123', 5000, 'usd') ->andReturn(['status' => 'succeeded', 'id' => 'ch_xyz']); // Bind the mock in the container $this->app->instance(StripeClient::class, $stripeClient); $gateway = app(PaymentGateway::class); $result = $gateway->processCharge('cus_abc123', 50.00); expect($result['status'])->toBe('succeeded'); }); ``` Мок `StripeClient` визначає очікуваний виклик методу `charge()` з конкретними параметрами. Директива `once()` гарантує, що метод буде викликано рівно один раз. Прив'язка мока до сервіс-контейнера через `$this->app->instance()` забезпечує його використання замість реального класу. ## Архітектурні тести: забезпечення конвенцій проєкту Архітектурні тести Pest дозволяють автоматизувати перевірку дотримання архітектурних правил проєкту. Це особливо корисно для великих команд, де важливо підтримувати єдині стандарти кодування. ```php // tests/Architecture/ArchitectureTest.php arch('controllers do not use Eloquent directly') ->expect('App\Http\Controllers') ->not->toUse('Illuminate\Database\Eloquent'); arch('services are final classes') ->expect('App\Services') ->toBeFinal(); arch('no debugging functions in production code') ->expect(['dd', 'dump', 'var_dump', 'ray']) ->not->toBeUsed(); ``` Перший тест забороняє контролерам використовувати Eloquent напряму, примушуючи працювати через сервісний шар. Другий вимагає, щоб усі сервіси були final-класами. Третій запобігає потраплянню debug-функцій у production-код. Pest також надає готові пресети для типових архітектурних перевірок: ```php // tests/Architecture/LaravelPresetTest.php arch()->preset()->laravel(); arch()->preset()->security(); arch()->preset()->php(); ``` Пресет `laravel()` включає перевірки специфічні для Laravel-застосунків, `security()` — перевірки безпеки, `php()` — загальні best practices PHP. ## Мутаційне тестування: оцінка реальної якості тестів Мутаційне тестування вносить невеликі зміни (мутації) у production-код та перевіряє, чи тести виявляють ці зміни. Високий відсоток виявлених мутацій свідчить про якісні тести, тоді як низький — про поверхневе покриття. ```bash # Run mutation testing on a specific class php artisan test --mutate --class=App\\Services\\PriceCalculator ``` Розглянемо різницю між тестом з високим покриттям, але низьким mutation score, та якісним тестом: ```php // Example: this test has high coverage but low mutation score it('calculates shipping cost', function () { $cost = calculateShipping(weight: 5.0, zone: 'domestic'); // Only checks that the result is numeric expect($cost)->toBeFloat(); }); // Improved: catches mutations by asserting the exact value it('calculates domestic shipping for 5kg package', function () { $cost = calculateShipping(weight: 5.0, zone: 'domestic'); // Exact assertion catches operator and value mutations expect($cost)->toBe(12.50); }); ``` Перший тест лише перевіряє тип результату — мутатор може змінити формулу обчислення, і тест все одно пройде. Другий тест перевіряє конкретне значення, тому будь-яка мутація буде виявлена. ## Комплексні тестові сценарії для співбесід На технічних співбесідах часто просять написати тести для типових бізнес-сценаріїв. Розглянемо приклад тестування публікації статті: ```php // tests/Feature/ArticlePublishingTest.php use App\Models\Article; use App\Models\User; it('publishes a draft article and updates the timestamp', function () { $author = User::factory()->create(['role' => 'editor']); $article = Article::factory() ->for($author, 'author') ->draft() ->create(['title' => 'Testing Best Practices']); $this->actingAs($author) ->patchJson("/api/articles/{$article->id}/publish") ->assertOk() ->assertJsonPath('data.status', 'published'); $article->refresh(); expect($article->status)->toBe('published') ->and($article->published_at)->not->toBeNull() ->and($article->published_at->isToday())->toBeTrue(); }); ``` Тест демонструє використання factory-станів (`draft()`), зв'язків між моделями (`for()`), HTTP-тестування та ланцюжкових assertions. Метод `refresh()` оновлює модель з бази даних для перевірки змін. Комплексне тестування API-автентифікації: ```php // tests/Feature/ApiAuthenticationTest.php use App\Models\User; describe('API Authentication', function () { it('rejects unauthenticated requests with 401', function () { $this->getJson('/api/profile') ->assertUnauthorized(); }); it('returns the authenticated user profile', function () { $user = User::factory()->create([ 'name' => 'John Doe', 'email' => 'john@example.com', ]); $this->actingAs($user) ->getJson('/api/profile') ->assertOk() ->assertJson([ 'data' => [ 'name' => 'John Doe', 'email' => 'john@example.com', ], ]); }); it('validates required fields on registration', function () { $this->postJson('/api/register', []) ->assertUnprocessable() ->assertJsonValidationErrors(['name', 'email', 'password']); }); }); ``` Цей набір тестів охоплює три ключові аспекти автентифікації: захист ендпоінтів від неавторизованого доступу, коректну роботу з авторизованим користувачем та валідацію вхідних даних. ## Питання технічних співбесід з тестування Laravel Нижче наведено типові питання, які задають на співбесідах для Laravel-розробників: **Базовий рівень:** - Яка різниця між Feature та Unit тестами в Laravel? - Як працює трейт RefreshDatabase і коли його використовувати? - Поясніть призначення методу actingAs() у тестах. - Чим відрізняється assertJson() від assertExactJson()? **Середній рівень:** - Як тестувати відправку email без реального надсилання листів? - Поясніть різницю між Mail::fake() та Mail::assertSent(). - Як мокати зовнішні HTTP-запити в тестах? - Що таке database factories і як використовувати стани? **Просунутий рівень:** - Як організувати тестування мікросервісної архітектури? - Поясніть концепцію мутаційного тестування та його переваги. - Як архітектурні тести Pest допомагають підтримувати якість коду? - Опишіть стратегію тестування event-driven систем у Laravel. **Практичні завдання:** - Напишіть тест для ендпоінта оновлення профілю користувача з валідацією. - Створіть тест для job, який обробляє платіж та надсилає сповіщення. - Напишіть архітектурний тест, що забороняє використання env() у сервісах. ## Висновок Тестування Laravel-застосунків у 2026 році вимагає володіння широким набором інструментів та технік. Pest значно спрощує написання тестів завдяки лаконічному синтаксису, а вбудована підтримка архітектурних тестів та мутаційного тестування дозволяє забезпечити високу якість кодової бази. Для успішного проходження технічних співбесід важливо не лише знати теорію, але й мати практичний досвід написання різних типів тестів. Рекомендується регулярно практикуватися на реальних проєктах, впроваджувати TDD-підхід та аналізувати mutation score для виявлення слабких місць у тестовому покритті. Постійне вдосконалення навичок тестування є ключовим фактором професійного зростання Laravel-розробника. Якісні тести не лише запобігають регресіям, але й слугують документацією до коду, полегшуючи онбординг нових членів команди та підтримку проєкту в довгостроковій перспективі. --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/uk/blog/laravel/laravel-testing-pest-mocking-best-practices