Тестирование middleware в Laravel

Middleware — это очень удобный инструмент Laravel для фильтрации запросов и выполнения других функций. Возникает вопрос, как убедиться, что middleware работает правильно. В данной статье я расскажу, как можно протестировать middleware.

Unit тесты

Первое, что приходит на ум, это unit-тесты. Но проблема в том, что unit-тест не проверяет, действительно ли middleware активно и вы не знаете, как оно поведет себя вместе с другими middleware в вашем приложении.

Интеграционные тесты

Использование интеграционных тестов для конкретных url в приложении решает часть проблем с unit-тестами, но при этом становится сложнее протестировать поведение самого middleware.

Тесты middleware

При написании тестов нам необходимо убедиться, что middleware работает так, как ожидается, и что middleware активно для определенных запросов.

Рассмотрим следующий пример:

<?php
namespace Tests\Unit;

use App\Http\Middleware\TrimStrings;
use Illuminate\Foundation\Testing\TestResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use Tests\TestCase;
class MiddlewareTest extends TestCase {
    public function testMiddleware() {
        Route::middleware(TrimStrings::class)->group(function () {
            Route::post('trim-strings-test', function (Request $request) {
                return response()->json([
                    'string' => $request->post('string'),
                ]);
            });
        });

        tap(
            $this->post('trim-strings-test', ['string' => ' bar   ']),
            function (TestResponse $response) {
                $this->assertEquals('bar', $response->json()['string']);
            }
        );
    }
}

Чтобы протестировать middleware (в данном примере я использую TrimStrings, который включен в Laravel), создается тестовый маршрут, для которого мы указываем тестируемый middleware, как мы используем их в самом приложении. Это позволяет проверить, что middleware действительно настроено и работает правильно.

Но как проверить, что middleware действительно активны там, где это нужно? Рассмотрим следующий пример. Добавим в файл с маршрутами следующий код:

Route::middleware(\App\Http\Middleware\TrimStrings::class)->group(function () {
    Route::post('test-middleware', function (Request $request) {})
        ->name('test-middleware');
});

Код проверки, что middleware действительно активен для маршрута будет выглядить так:

<?php
namespace Tests\Unit;

use App\Http\Middleware\TrimStrings;
use Illuminate\Support\Facades\Route;
use Tests\TestCase;
class MiddlewareActiveTest extends TestCase {
    public function testRouteHasMiddleware() {
        $this->assertArrayHasKey(
            TrimStrings::class,
            array_flip(Route::getRoutes()->getByName('test-middleware')->gatherMiddleware())
        );
    }
}

В данном случае, для каждого маршрута, или группы маршрутов, которые нужно проверить, мы получаем массив middleware и проверяем, что он содержит нужный нам класс.

Код из этой статьи можно скачать с GitHub: https://github.com/RusinovIG/blog-examples/pull/2 и запустить локально.

Заключение

Мы рассмотрели, как можно просто и удобно протестировать корректность работы middleware, а так же проверить, что они действительно применяются к нужным маршрутам. Такая проверка может быть особенно полезной, чтобы убедиться, что все маршруты вашего api защищены, если вы используете middleware для проверки прав доступа.

Добавить комментарий