Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як не пропустити N+1 запити в тестах?

Зробити так, щоб N+1 ламав тест, а не тихо пригальмовував сторінку в проді.

1. Заборонити ліниве завантаження поза продакшеном:

// AppServiceProvider::boot()
Model::preventLazyLoading(! $this->app->isProduction());

Тепер звернення до незавантаженого зв'язку в циклі кидає LazyLoadingViolationException - і будь-який тест сторінки, що це робить, впаде. Часто вмикають разом Model::shouldBeStrict(), який ще й ловить звернення до відсутніх атрибутів.

2. Обмежити кількість запитів для критичної сторінки (Laravel 13):

it('loads the orders page in a fixed number of queries', function () {
    Order::factory()->count(20)->hasItems(3)->create();

    $this->expectsDatabaseQueryCount(4);

    $this->actingAs(User::factory()->admin()->create())
        ->get('/admin/orders')
        ->assertOk();
});

Важливо: тестові дані мають бути «множинними». N+1 не видно на одному записі - один пост з одним коментарем дасть два запити і з with(), і без. Тест має створювати кілька записів, щоб різниця між «2 запити» і «21 запит» проявилася.

Альтернатива в Laravel 12+ - Model::automaticallyEagerLoadRelationships(), що сам довантажує зв'язки для всієї колекції. Але тест з лічильником запитів корисний і тоді: він фіксує, що сторінка не деградує з часом.

Докладніше в документації: Заборона лінивого завантаження

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання