- Введение
- Выполнение запросов
- Тестирование JSON API
- Тестирование загрузки файлов
- Тестирование шаблонной системы
- Доступные утверждения
Laravel предоставляет очень гибкий API для выполнения HTTP-запросов к вашему приложению и проверки ответов. Например, взгляните на функциональный тест, расположенный ниже:
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Tests\TestCase;
class ExampleTest extends TestCase
{
/**
* Базовый пример теста.
*
* @return void
*/
public function test_a_basic_request()
{
$response = $this->get('/');
$response->assertStatus(200);
}
}
Метод get
отправляет в приложение запрос GET
, а метод assertStatus
утверждает, что возвращаемый ответ должен иметь указанный код состояния HTTP. Помимо этого простого утверждения, Laravel также содержит множество утверждений для проверки заголовков ответов, содержимого, структуры JSON и многого другого.
Чтобы сделать запрос к вашему приложению, вы можете вызвать в своем тесте методы get
, post
, put
, patch
, или delete
. Эти методы фактически не отправляют вашему приложению «настоящий» HTTP-запрос. Вместо этого внутри моделируется полный сетевой запрос.
Вместо того, чтобы возвращать экземпляр Illuminate\Http\Response
, методы тестового запроса возвращают экземпляр Illuminate\Testing\TestResponse
, который предоставляет множество полезных утверждений, которые позволяют вам инспектировать ответы вашего приложения:
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Tests\TestCase;
class ExampleTest extends TestCase
{
/**
* Базовый пример теста.
*
* @return void
*/
public function test_a_basic_request()
{
$response = $this->get('/');
$response->assertStatus(200);
}
}
{tip} Для удобства посредник CSRF автоматически отключается при запуске тестов.
Вы можете использовать метод withHeaders
для настройки заголовков запроса перед его отправкой в приложение. Этот метод позволяет вам добавлять в запрос любые пользовательские заголовки:
<?php
namespace Tests\Feature;
use Tests\TestCase;
class ExampleTest extends TestCase
{
/**
* Пример базового функционального теста.
*
* @return void
*/
public function test_interacting_with_headers()
{
$response = $this->withHeaders([
'X-Header' => 'Value',
])->post('/user', ['name' => 'Sally']);
$response->assertStatus(201);
}
}
Вы можете использовать методы withCookie
или withCookies
для установки значений файлов Cookies перед отправкой запроса. Метод withCookie
принимает имя и значение Cookie в качестве двух аргументов, а метод withCookies
принимает массив пар имя / значение:
<?php
namespace Tests\Feature;
use Tests\TestCase;
class ExampleTest extends TestCase
{
public function test_interacting_with_cookies()
{
$response = $this->withCookie('color', 'blue')->get('/');
$response = $this->withCookies([
'color' => 'blue',
'name' => 'Taylor',
])->get('/');
}
}
Laravel предоставляет несколько помощников для взаимодействия с сессией во время HTTP-тестирования. Во-первых, вы можете установить данные сессии, передав массив, используя метод withSession
. Это полезно для загрузки сессии данными перед отправкой запроса вашему приложению:
<?php
namespace Tests\Feature;
use Tests\TestCase;
class ExampleTest extends TestCase
{
public function test_interacting_with_the_session()
{
$response = $this->withSession(['banned' => false])->get('/');
}
}
Сессия Laravel обычно используется для сохранения состояния текущего аутентифицированного пользователя. Таким образом, вспомогательный метод actingAs
предоставляет простой способ аутентифицировать переданного пользователя как текущего. Например, мы можем использовать фабрику модели для генерации и аутентификации пользователя:
<?php
namespace Tests\Feature;
use App\Models\User;
use Tests\TestCase;
class ExampleTest extends TestCase
{
public function test_an_action_that_requires_authentication()
{
$user = User::factory()->create();
$response = $this->actingAs($user)
->withSession(['banned' => false])
->get('/');
}
}
Вы также можете указать, какой охранник должен использоваться для аутентификации переданного пользователя, передав имя охранника в качестве второго аргумента методу actingAs
:
$this->actingAs($user, 'api')
После выполнения тестового запроса к вашему приложению методы dump
, dumpHeaders
, и dumpSession
могут быть использованы для проверки и отладки содержимого ответа:
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Tests\TestCase;
class ExampleTest extends TestCase
{
/**
* Базовый пример теста.
*
* @return void
*/
public function test_basic_test()
{
$response = $this->get('/');
$response->dumpHeaders();
$response->dumpSession();
$response->dump();
}
}
Laravel также содержит несколько помощников для тестирования API-интерфейсов JSON и их ответов. Например, методы json
, getJson
, postJson
, putJson
, patchJson
, deleteJson
, и optionsJson
могут использоваться для отправки запросов JSON с различными HTTP-командами. Вы также можете легко передавать данные и заголовки этим методам. Для начала давайте напишем тест, чтобы сделать запрос POST
к /api/user
и убедиться, что были возвращены ожидаемые данные JSON:
<?php
namespace Tests\Feature;
use Tests\TestCase;
class ExampleTest extends TestCase
{
/**
* Пример базового функционального теста.
*
* @return void
*/
public function test_making_an_api_request()
{
$response = $this->postJson('/api/user', ['name' => 'Sally']);
$response
->assertStatus(201)
->assertJson([
'created' => true,
]);
}
}
Кроме того, к данным ответа JSON можно получить доступ как к переменным массива в ответе, что позволяет удобно проверять отдельные значения, возвращаемые в JSON-ответе:
$this->assertTrue($response['created']);
{tip} Метод
assertJson
преобразует ответ в массив и используетPHPUnit::assertArraySubset
для проверки того, что переданный массив существует в ответе JSON, возвращаемом приложением. Итак, если в ответе JSON есть другие свойства, этот тест все равно будет проходить, пока присутствует переданный фрагмент.
Как упоминалось ранее, метод assertJson
может использоваться для подтверждения наличия фрагмента JSON в ответе JSON. Если вы хотите убедиться, что данный массив в точности соответствует JSON, возвращаемому вашим приложением, вы должны использовать метод assertExactJson
:
<?php
namespace Tests\Feature;
use Tests\TestCase;
class ExampleTest extends TestCase
{
/**
* Пример базового функционального теста.
*
* @return void
*/
public function test_asserting_an_exact_json_match()
{
$response = $this->json('POST', '/user', ['name' => 'Sally']);
$response
->assertStatus(201)
->assertExactJson([
'created' => true,
]);
}
}
Если вы хотите убедиться, что ответ JSON содержит данные по указанному пути, вам следует использовать метод assertJsonPath
:
<?php
namespace Tests\Feature;
use Tests\TestCase;
class ExampleTest extends TestCase
{
/**
* Пример базового функционального теста.
*
* @return void
*/
public function test_asserting_a_json_paths_value()
{
$response = $this->json('POST', '/user', ['name' => 'Sally']);
$response
->assertStatus(201)
->assertJsonPath('team.owner.name', 'Darian');
}
}
Класс Illuminate\Http\UploadedFile
предоставляет метод fake
, который можно использовать для создания фиктивных файлов или изображений для тестирования. Это, в сочетании с методом fake
фасада Storage
, значительно упрощает тестирование загрузки файлов. Например, вы можете объединить эти две функции, чтобы легко протестировать форму загрузки аватара:
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
class ExampleTest extends TestCase
{
public function test_avatars_can_be_uploaded()
{
Storage::fake('avatars');
$file = UploadedFile::fake()->image('avatar.jpg');
$response = $this->post('/avatar', [
'avatar' => $file,
]);
Storage::disk('avatars')->assertExists($file->hashName());
}
}
Если вы хотите подтвердить, что переданный файл не существует, вы можете использовать метод assertMissing
фасада Storage
:
Storage::fake('avatars');
// ...
Storage::disk('avatars')->assertMissing('missing.jpg');
При создании файлов с использованием метода fake
, предоставляемого классом UploadedFile
, вы можете указать ширину, высоту и размер изображения (в килобайтах), чтобы лучше протестировать правила валидации вашего приложения:
UploadedFile::fake()->image('avatar.jpg', $width, $height)->size(100);
Помимо создания изображений, вы можете создавать файлы любого другого типа, используя метод create
:
UploadedFile::fake()->create('document.pdf', $sizeInKilobytes);
При необходимости вы можете передать аргумент $mimeType
методу, чтобы явно определить MIME-тип, который должен возвращать файл:
UploadedFile::fake()->create(
'document.pdf', $sizeInKilobytes, 'application/pdf'
);
Laravel также позволяет отображать шаблоны без имитации HTTP-запроса к приложению. Для этого вы можете вызвать в своем тесте метод view
. Метод view
принимает имя шаблона и необязательный массив данных. Метод возвращает экземпляр Illuminate\Testing\TestView
, который предлагает несколько методов для удобных утверждений о содержимом шаблона:
<?php
namespace Tests\Feature;
use Tests\TestCase;
class ExampleTest extends TestCase
{
public function test_a_welcome_view_can_be_rendered()
{
$view = $this->view('welcome', ['name' => 'Taylor']);
$view->assertSee('Taylor');
}
}
Класс TestView
содержит следующие методы утверждения: assertSee
, assertSeeInOrder
, assertSeeText
, assertSeeTextInOrder
, assertDontSee
и assertDontSeeText
.
При необходимости вы можете получить необработанное отрисованное содержимое шаблона, преобразовав экземпляр TestView
в строку:
$contents = (string) $this->view('welcome');
Некоторые шаблоны могут зависеть от ошибок, хранящихся в глобальной коллекции ошибок Laravel. Чтобы добавить в эту коллекцию сообщения об ошибках, вы можете использовать метод withViewErrors
:
$view = $this->withViewErrors([
'name' => ['Please provide a valid name.']
])->view('form');
$view->assertSee('Please provide a valid name.');
Если необходимо, вы можете использовать метод blade
для анализа и отрисовки необработанной строки Blade. Подобно методу view
, метод blade
возвращает экземпляр Illuminate\Testing\TestView
:
$view = $this->blade(
'<x-component :name="$name" />',
['name' => 'Taylor']
);
$view->assertSee('Taylor');
Вы можете использовать метод component
для анализа и отрисовки компонента Blade. Как и метод view
, метод component
возвращает экземпляр Illuminate\Testing\TestView
:
$view = $this->component(Profile::class, ['name' => 'Taylor']);
$view->assertSee('Taylor');
Класс Illuminate\Testing\TestResponse
содержит множество своих методов утверждения, которые вы можете использовать при тестировании вашего приложения. К этим утверждениям можно получить доступ в ответе, возвращаемом тестовыми методами json
, get
, post
, put
, и delete
:
- assertCookie
- assertCookieExpired
- assertCookieNotExpired
- assertCookieMissing
- assertCreated
- assertDontSee
- assertDontSeeText
- assertExactJson
- assertForbidden
- assertHeader
- assertHeaderMissing
- assertJson
- assertJsonCount
- assertJsonFragment
- assertJsonMissing
- assertJsonMissingExact
- assertJsonMissingValidationErrors
- assertJsonPath
- assertJsonStructure
- assertJsonValidationErrors
- assertLocation
- assertNoContent
- assertNotFound
- assertOk
- assertPlainCookie
- assertRedirect
- assertSee
- assertSeeInOrder
- assertSeeText
- assertSeeTextInOrder
- assertSessionHas
- assertSessionHasInput
- assertSessionHasAll
- assertSessionHasErrors
- assertSessionHasErrorsIn
- assertSessionHasNoErrors
- assertSessionDoesntHaveErrors
- assertSessionMissing
- assertStatus
- assertSuccessful
- assertUnauthorized
- assertViewHas
- assertViewHasAll
- assertViewIs
- assertViewMissing
Утверждает, что ответ содержит переданный cookie:
$response->assertCookie($cookieName, $value = null);
Утверждает, что в ответе содержится переданный cookie и срок его действия истек:
$response->assertCookieExpired($cookieName);
Утверждает, что в ответе содержится переданный cookie и срок его действия не истек:
$response->assertCookieNotExpired($cookieName);
Утверждает, что ответ не содержит переданный cookie:
$response->assertCookieMissing($cookieName);
Утверждает, что ответ имеет код 201
состояния HTTP:
$response->assertCreated();
Утверждает, что переданная строка не содержится в ответе, возвращаемом приложением. Это утверждение автоматически экранирует переданную строку, если вы не передадите второй аргумент как false
:
$response->assertDontSee($value, $escaped = true);
Утверждает, что переданная строка не содержится в тексте ответа. Это утверждение автоматически экранирует переданную строку, если вы не передадите второй аргумент как false
. Этот метод передаст содержимое ответа PHP-функции strip_tags
перед тем, как выполнить утверждение:
$response->assertDontSeeText($value, $escaped = true);
Утверждает, что ответ содержит точное совпадение указанных данных JSON:
$response->assertExactJson(array $data);
Утверждает, что ответ имеет код 403
состояния HTTP – forbidden
:
$response->assertForbidden();
Утверждает, что переданный заголовок и значение присутствуют в ответе:
$response->assertHeader($headerName, $value = null);
Утверждает, что переданный заголовок отсутствует в ответе:
$response->assertHeaderMissing($headerName);
Утверждает, что ответ содержит указанные данные JSON:
$response->assertJson(array $data, $strict = false);
Метод assertJson
преобразует ответ в массив и использует PHPUnit::assertArraySubset
для проверки того, что переданный массив существует в ответе JSON, возвращаемом приложением. Итак, если в ответе JSON есть другие свойства, этот тест все равно будет проходить, пока присутствует переданный фрагмент.
Утверждает, что ответ JSON имеет массив с ожидаемым количеством элементов указанного ключа:
$response->assertJsonCount($count, $key = null);
Утверждает, что ответ содержит указанные данные JSON в любом месте ответа:
Route::get('/users', function () {
return [
'users' => [
[
'name' => 'Taylor Otwell',
],
],
];
});
$response->assertJsonFragment(['name' => 'Taylor Otwell']);
Утверждает, что ответ не содержит указанных данных JSON:
$response->assertJsonMissing(array $data);
Утверждает, что ответ не содержит точных указанных данных JSON:
$response->assertJsonMissingExact(array $data);
Утверждает, что ответ не содержит ошибок валидации JSON для переданных ключей:
$response->assertJsonMissingValidationErrors($keys);
Утверждает, что ответ содержит конкретные данные по указанному пути:
$response->assertJsonPath($path, array $data, $strict = true);
Например, если ответ JSON, возвращаемый вашим приложением, содержит следующие данные:
{
"user": {
"name": "Steve Schoger"
}
}
Вы можете утверждать, что свойство name
объекта user
соответствует переданному значению следующим образом:
$response->assertJsonPath('user.name', 'Steve Schoger');
Утверждает, что ответ имеет переданную структуру JSON:
$response->assertJsonStructure(array $structure);
Например, если ответ JSON, возвращаемый вашим приложением, содержит следующие данные:
{
"user": {
"name": "Steve Schoger"
}
}
Вы можете утверждать, что структура JSON соответствует вашим ожиданиям, например:
$response->assertJsonStructure([
'user' => [
'name',
]
]);
Утверждает, что ответ содержит переданные ошибки валидации JSON для переданных ключей. Этот метод следует использовать при утверждении ответов, в которых ошибки валидации возвращаются как структура JSON, а не кратковременно передаются в сесиию:
$response->assertJsonValidationErrors(array $data);
Утверждает, что ответ имеет переданное значение URI в заголовке Location
:
$response->assertLocation($uri);
Утверждает, что ответ имеет код 204
состояния HTTP – no content
:
$response->assertNoContent($status = 204);
Утверждает, что ответ имеет код 404
состояния HTTP – not found
:
$response->assertNotFound();
Утверждает, что ответ имеет код 200
состояния HTTP – OK
:
$response->assertOk();
Утверждает, что ответ содержит переданный незашифрованный cookie:
$response->assertPlainCookie($cookieName, $value = null);
Утверждает, что ответ является перенаправлением на указанный URI:
$response->assertRedirect($uri);
Утверждает, что переданная строка содержится в ответе. Это утверждение автоматически экранирует переданную строку, если вы не передадите второй аргумент как false
:
$response->assertSee($value, $escaped = true);
Утверждает, что переданные строки содержатся в ответе в указанном порядке. Это утверждение автоматически экранирует переданные строки, если вы не передадите второй аргумент как false
:
$response->assertSeeInOrder(array $values, $escaped = true);
Утверждает, что переданная строка содержится в тексте ответа. Это утверждение автоматически экранирует переданную строку, если вы не передадите второй аргумент как false
. Этот метод передаст содержимое ответа PHP-функции strip_tags
перед тем, как выполнить утверждение:
$response->assertSeeText($value, $escaped = true);
Утверждает, что переданные строки содержатся в тексте ответа в указанном порядке. Это утверждение автоматически экранирует переданные строки, если вы не передадите второй аргумент как false
. Этот метод передаст содержимое ответа PHP-функции strip_tags
перед тем, как выполнить утверждение:
$response->assertSeeTextInOrder(array $values, $escaped = true);
Утверждает, что сессия содержит переданный фрагмент данных:
$response->assertSessionHas($key, $value = null);
Утверждает, что сессия имеет переданное значение в массиве входящих данных кратковременного сохранения:
$response->assertSessionHasInput($key, $value = null);
Утверждает, что сессия содержит переданный массив пар ключ / значение:
$response->assertSessionHasAll(array $data);
Например, если сессия вашего приложения содержит ключи name
и status
, вы можете утверждать, что оба они существуют и имеют указанные значения, например:
$response->assertSessionHasAll([
'name' => 'Taylor Otwell',
'status' => 'active',
]);
Утверждает, что сессия содержит ошибку для переданных $keys
. Если $keys
является ассоциативным массивом, следует утверждать, что сессия содержит конкретное сообщение об ошибке (значение) для каждого поля (ключа). Этот метод следует использовать при тестировании маршрутов, которые передают ошибки валидации в сессию вместо того, чтобы возвращать их в виде структуры JSON:
$response->assertSessionHasErrors(
array $keys, $format = null, $errorBag = 'default'
);
Например, чтобы утверждать, что поля name
и email
содержат сообщения об ошибках валидации, которые были переданы в сессию, вы можете вызвать метод assertSessionHasErrors
следующим образом:
$response->assertSessionHasErrors(['name', 'email']);
Или вы можете утверждать, что переданное поле имеет конкретное сообщение об ошибке валидации:
$response->assertSessionHasErrors([
'name' => 'The given name was invalid.'
]);
Утверждает, что сессия содержит ошибку для переданных $keys
в конкретной коллекции ошибок. Если $keys
является ассоциативным массивом, убедитесь, что сессия содержит конкретное сообщение об ошибке (значение) для каждого поля (ключа) в коллекции ошибок:
$response->assertSessionHasErrorsIn($errorBag, $keys = [], $format = null);
Утверждает, что в сессии нет ошибок валидации:
$response->assertSessionHasNoErrors();
Утверждает, что в сессии нет ошибок валидации для переданных ключей:
$response->assertSessionDoesntHaveErrors($keys = [], $format = null, $errorBag = 'default');
Утверждает, что сессия не содержит переданного ключа:
$response->assertSessionMissing($key);
Утверждает, что ответ имеет указанный код $code
состояния HTTP:
$response->assertStatus($code);
Утверждает, что ответ имеет код >= 200
и < 300
состояния HTTP – successful
:
$response->assertSuccessful();
Утверждает, что ответ имеет код 401
состояния HTTP – unauthorized
:
$response->assertUnauthorized();
Утверждает, что шаблон ответа содержит переданный фрагмент данных:
$response->assertViewHas($key, $value = null);
Кроме того, данные шаблона могут быть доступны как переменные массива в ответе, что позволяет вам удобно инспектировать их:
$this->assertEquals('Taylor', $response['name']);
Утверждает, что в шаблон ответа содержит переданный список данных:
$response->assertViewHasAll(array $data);
Этот метод может использоваться, чтобы утверждать, что шаблон просто содержит данные с соответствующими переданными ключами:
$response->assertViewHasAll([
'name',
'email',
]);
Или вы можете утверждать, что данные шаблона присутствуют и имеют определенные значения:
$response->assertViewHasAll([
'name' => 'Taylor Otwell',
'email' => 'taylor@example.com,',
]);
Утверждает, что маршрутом был возвращен указанный шаблон:
$response->assertViewIs($value);
Утверждает, что переданный ключ данных не был доступен для шаблона, возвращенного ответом приложения:
$response->assertViewMissing($key);
Laravel также содержит множество утверждений, связанных с аутентификацией, которые вы можете использовать в функциональных тестах вашего приложения. Обратите внимание, что эти методы вызываются в самом тестовом классе, а не в экземпляре Illuminate\Testing\TestResponse
, возвращаемом такими методами, как get
и post
.
Утверждает, что пользователь аутентифицирован:
$this->assertAuthenticated($guard = null);
Утверждает, что пользователь не аутентифицирован:
$this->assertGuest($guard = null);
Утверждает, что конкретный пользователь аутентифицирован:
$this->assertAuthenticatedAs($user, $guard = null);