Автор оригинала: David Wong.
Эта статья переслана из профессионального сообщества разработчиков laravel, оригинальная ссылка: https://learnku.com/laravel/t…
В этой статье я покажу вам пример использования HTTP для тестирования промежуточного программного обеспечения. Тестирование на уровне HTTP более адаптируемо к изменениям и более читабельно.
В недавней полной трансляции с Адамом Уотаном и Тейлором Отуэллом( http://www.fullstackradio.com/72 ) В программе приятно слышать, что они нашли много практических преимуществ в тестировании HTTP. Я нахожу, что HTTP-тесты легче писать и поддерживать, но мне кажется , что я тестирую неправильно ™ или не моделирую (объект), изолирую каждый тестовый элемент так же, как обман. Если вы еще не слышали этот эпизод, послушайте его. В нем полно хороших практических советов по тестированию.
вводить
Ранее в этом году я создал промежуточное программное обеспечение для проверки и защиты веб-крючка mailgun в одном из своих проектов и описал это в разделе входящая обработка электронной почты в larravel с помощью mailgun в новостях larravel. Вкратце, я продемонстрирую, как использовать промежуточное программное обеспечение laravel для проверки веб-соединения mailgun (для обеспечения веб-соединения) при обработке входящей электронной почты на самом деле Из почтового пистолета).
При настройке основной части веб-крючка mailgun подпись как часть полезной нагрузки HTTP post рекомендуется проверять с помощью подписи, метки времени и маркера, предоставленных rquest для защиты вашего веб-крючка. Это полное промежуточное программное обеспечение, которое я выпустил:
Промежуточное программное обеспечение принимает только POST Запросите и сравните входящую подпись с подписью, сгенерированной с помощью ключа mailgun.
Я видел различные способы тестирования промежуточного программного обеспечения, такие как создание его непосредственно в модульных тестах, моделирование объектов по мере необходимости и прямой запуск промежуточного программного обеспечения. В этой статье я покажу вам, как протестировать это промежуточное программное обеспечение с использованием более высокого уровня HTTP-тестирования. Весь ваш стек будет запущен в тесте, Сделает вас более уверенным Ваше приложение будет работать так, как ожидалось.
Не привязывайте тест непосредственно к конкретной реализации промежуточного программного обеспечения Это важное преимущество, о котором вы можете узнать. Мы можем полностью переработать промежуточное программное обеспечение без изменения каких-либо тестов или моделирования обновлений, чтобы убедиться, что промежуточное программное обеспечение работает должным образом. Я уверен, что вы обнаружите, что эти тесты будут более надежными.
для настройки
Давайте воспользуемся примером проекта laravel 5.5 для быстрого создания теста вышеупомянутого промежуточного программного обеспечения:
$ laravel new middleware-tests #Switch to the middleware tests folder $ cd $_ $ php artisan make:middleware ValidateMailgunWebhook
Получите приведенный выше код промежуточного программного обеспечения и вставьте его в файл промежуточного программного обеспечения.
Затем добавьте промежуточное программное обеспечение в app/Http/Kernel.php В документе:
protected $routeMiddleware = [
// ...
'mailgun.webhook' => \App\Http\Middleware\ValidateMailgunWebhook::class,
];
Написание HTTP-тестов
Нам даже не нужно писать никаких тестов для этого промежуточного программного обеспечения routes/api.php Чтобы проверить это!
Во-первых, давайте создадим файл функционального теста:
$ php artisan make:test SecureMailgunWebhookTest
Проверьте промежуточное программное обеспечение mailgun. Вот что мы хотим протестировать, чтобы убедиться, что промежуточное программное обеспечение работает должным образом:
- Любой HTTP-глагол, отличный от
POSTДолжно вызвать403 ЗапрещеноОтвет. - Должна быть создана неверная подпись
403 ЗапрещеноОтвет. - Действительная подпись должна пройти и попасть на вызываемый маршрут.
- Старая метка времени должна вызывать
403 ЗапрещеноОтвет.
Тестирование недопустимых методов HTTP
С помощью этого введения давайте напишем наш первый тест и настроим наш тест.
Обновление с помощью SecureMailgunWebhookTest Документ:
set('services.mailgun.secret', 'secret');
\Route::middleware('mailgun.webhook')->any('/_test/webhook', function () {
return 'OK';
});
}
/** @test */
public function it_forbids_non_post_methods()
{
$this->withoutExceptionHandling();
$exceptionCount = 0;
$httpVerbs = ['get', 'put', 'patch', 'delete'];
foreach ($httpVerbs as $httpVerb) {
try {
$response = $this->$httpVerb('/_test/webhook');
} catch (HttpException $e) {
$exceptionCount++;
$this->assertEquals(Response::HTTP_FORBIDDEN, $e->getStatusCode());
$this->assertEquals('Only POST requests are allowed.', $e->getMessage());
}
}
if (count($httpVerbs) === $exceptionCount) {
return;
}
$this->fail('Expected a 403 forbidden');
}
}
остаться Настройка() Метод, мы определяем поддельный ключ почтового пистолета, чтобы мы могли писать наши тесты против этого ключа, а затем использовать any() Метод маршрутизации определяет глобальный (охватывающий все) маршрут. Наша маршрутизация позволит нам использовать поддельный тестовый маршрут для выполнения HTTP-запросов с использованием промежуточного программного обеспечения.
Введено в laravel 5.5 без обработки исключений() Этот метод означает, что мы можем сами поймать брошенное исключение в тесте, вместо того, чтобы использовать его HTTP Ответ для отображения этого исключения.
попробуй/поймай Обеспечит, чтобы для каждого HTTP Запросить захват для HttpException , также предоставляет счетчик инкрементных исключений. Если мы зафиксируем количество исключений с помощью нашего теста HTTP Если количество запросов совпадает, тест проходит. В противном случае, если наш запрос не вызовет исключения $, будет вызван метод this->fail () .
Я предпочитаю метод перехвата и утверждения исключений использованию аннотаций. Это заставляет меня чувствовать себя яснее, и я могу утверждать исключения, чтобы убедиться, что они соответствуют моим ожиданиям.
Вы можете запустить тест функции промежуточного программного обеспечения напрямую, используя следующую команду phpunit:
# Run all tests in the file $ ./vendor/bin/phpunit tests/Feature/SecureMailgunWebhookTest.php # Filter a specific method $ ./vendor/bin/phpunit \ tests/Feature/SecureMailgunWebhookTest.php \ --filter=it_forbids_non_post_methods
Проверка недействительной подписи
Следующий тест проверяет, не являются ли недопустимые подписи причиной 403 Запрещенной ошибки 。 Этот тест отличается от первого теста тем, что он использует POST Метод, но отправить неверные данные запроса:
/** @test */
public function it_aborts_with_an_invalid_signature()
{
$this->withoutExceptionHandling();
try {
$this->post('/_test/webhook', [
'timestamp' => abs(time() - 100),
'token' => 'invalid-token',
'signature' => 'invalid-signature',
]);
} catch (HttpException $e) {
$this->assertEquals(Response::HTTP_FORBIDDEN, $e->getStatusCode());
$this->assertEquals('The webhook signature was invalid.', $e->getMessage());
return;
}
$this->fail('Expected the webhook signature to be invalid.');
}
Мы передаем поддельные данные, которые приведут к недействительной подписи, а затем утверждаем, что HttpException Задается правильный статус ответа и сообщения.
Проверьте правильность подписи
Когда webhook отправляет действительную подпись, маршрут обрабатывает ответ, не прерывая промежуточное программное обеспечение. Промежуточное программное обеспечение вызывает verify() , а затем вызывается, когда подпись совпадает $next( ) :
if ($this->verify($request)) {
return $next($request);
}
Чтобы написать этот тест, нам нужно отправить действительную подпись, метку времени и токен. Мы создадим хэш-версию SHA256 в тестовом классе, которая является почти копией того же метода в промежуточном программном обеспечении. Как промежуточное программное обеспечение, так и наши тесты будут использоваться в setup() Метод services.mailgun.secret Ключ:
/** @test */
public function it_passes_with_a_valid_signature()
{
$this->withoutExceptionHandling();
$timestamp = time();
$token = 'token';
$response = $this->post('/_test/webhook', [
'timestamp' => $timestamp,
'token' => $token,
'signature' => $this->buildSignature($timestamp, $token),
]);
$this->assertEquals('OK', $response->getContent());
}
protected function buildSignature($timestamp, $token)
{
return hash_hmac(
'sha256',
sprintf('%s%s', $timestamp, $token),
config('services.mailgun.secret')
);
}
Наш тест использует тот же код для создания подписей в промежуточном программном обеспечении, поэтому мы можем генерировать действительные подписи, ожидаемые промежуточным программным обеспечением. В конце теста мы утверждаем, что содержимое ответа, возвращенного в пути теста, равно “ОК”..
Тест не удался со старой меткой времени
Еще одна мера предосторожности, которую принимает наше промежуточное программное обеспечение, – это если метка времени Если приложение старое, запрос не может быть продолжен. Тест похож на другие тесты, в которых мы утверждаем, что потерпели неудачу, но на этот раз мы делаем все допустимым (подписи и токены) за исключением Вне метки времени:
/** @test */
public function it_fails_with_an_old_timestamp()
{
try {
$this->withoutExceptionHandling();
$timestamp = abs(time() - 16);
$token = 'token';
$response = $this->post('/_test/webhook', [
'timestamp' => $timestamp,
'token' => $token,
'signature' => $this->buildSignature($timestamp, $token),
]);
} catch (HttpException $e) {
$this->assertEquals(Response::HTTP_FORBIDDEN, $e->getStatusCode());
$this->assertEquals('The webhook signature was invalid.', $e->getMessage());
return;
}
$this->fail('The timestamp should have failed verification.');
}
Пристальное внимание $метка времени(time() - 16); Это приведет к аннулированию сравнения временных меток промежуточного программного обеспечения.
Учить больше
Это быстрый рендеринг тестового промежуточного программного обеспечения на уровне HTTP. Я предпочитаю этот уровень тестирования, потому что использование насмешек над промежуточным программным обеспечением может быть утомительным и привязанным к конкретной реализации. Если я решу провести рефакторинг позже, мне, вероятно, придется переписать свои тесты в соответствии с новым промежуточным программным обеспечением. При тестировании HTTP я мог свободно рефакторировать промежуточное программное обеспечение и ожидать тех же результатов.
Написание [HTTP-теста] в laravel( https://laravel.com/docs/5.5/… ) Это очень просто, и я обнаружил, что провожу больше тестов на этом уровне. Я верю, что тесты, которые я пишу, легко понять, потому что мы ни над чем не издеваемся. Вы должны быть знакомы с утверждением (функцией) набора тестов laravel для тестирования. Эти инструменты делают ваше тестирование проще и, смею сказать, интереснее.
Если вы не знакомы с тестированием, вы также можете просмотреть тестируемый laravel в новостях laravel. Я тоже прошел через этот процесс; если вы только начинаете тестировать веб-приложение, это хороший ресурс.
Оригинал: “https://developpaper.com/testing-larravel-middleware-using-http-test/”