HTTP テスト
テストの中でアプリにリクエストを送り、返ってきたレスポンスを確かめる方法と、使えるアサーション(確認の命令)の一覧を説明します。
HTTP テストは、アプリに「このページをください」とお願い(リクエスト)を送って、返ってきた答え(レスポンス)が正しいかを確かめるテストです。ブラウザを開いて自分で押してみる作業を、プログラムにやらせるイメージです。Laravel は、リクエストを送る命令と、答えを調べる命令(アサーション)をたくさん用意しています。
テストの置き場所や動かし方は、テストのはじめかたを先に見てください。
最初のテスト#
次は、トップページ(/)にアクセスして、ステータスコード(結果を表す番号。200 は「成功」)が 200 かを確かめるテストです。
Pest で書くとき:
<?php
test('the application returns a successful response', function () {
$response = $this->get('/');
$response->assertStatus(200);
});
PHPUnit で書くとき:
<?php
namespace Tests\Feature;
use Tests\TestCase;
class ExampleTest extends TestCase
{
/**
* A basic test example.
*/
public function test_the_application_returns_a_successful_response(): void
{
$response = $this->get('/');
$response->assertStatus(200);
}
}
get は GET リクエストを送る命令で、assertStatus は「返ってきたステータスコードがこの番号のはず」と確かめる命令です。ほかにも、ヘッダー(リクエストやレスポンスに付く説明書き)・本文・JSON の形などを確かめる命令があります。
リクエストを送る#
リクエストを送るには、テストの中で get・post・put・patch・delete を呼びます。実際のネットワークは使わず、アプリの内側で通信のまねをします。
これらは、ふつうの Illuminate\Http\Response ではなく Illuminate\Testing\TestResponse を返します。この TestResponse に、下の「アサーションの一覧」にある確認の命令がそろっています。
<?php
test('basic request', function () {
$response = $this->get('/');
$response->assertStatus(200);
});
ふつうは、1つのテストの中では、リクエストは1回だけにします。1つのテストで何回も送ると、思わぬ動きになることがあります。
補足
テストを動かすあいだは、CSRF 対策のミドルウェアは自動で止まります。
ヘッダーを付ける#
withHeaders で、リクエストに好きなヘッダーを付けて送れます。
<?php
test('interacting with headers', function () {
$response = $this->withHeaders([
'X-Header' => 'Value',
])->post('/user', ['name' => 'Sally']);
$response->assertStatus(201);
});
Cookie を付ける#
withCookie は名前と値を1組、withCookies は名前と値の連想配列(名前と値の組の並び)を、リクエストの前に設定します。
<?php
test('interacting with cookies', function () {
$response = $this->withCookie('color', 'blue')->get('/');
$response = $this->withCookies([
'color' => 'blue',
'name' => 'Taylor',
])->get('/');
//
});
セッションとログイン#
セッションに、リクエストの前に値を入れておくには withSession を使います。
<?php
test('interacting with the session', function () {
$response = $this->withSession(['banned' => false])->get('/');
//
});
セッションは、ふつう「いまログインしている人」を覚えておくために使われます。そのため、ある人をログイン中にするための actingAs が用意されています。次の例は、ファクトリ(ためしのデータを作るしくみ)で作ったユーザーでログインした状態にします。
<?php
use App\Models\User;
test('an action that requires authentication', function () {
$user = User::factory()->create();
$response = $this->actingAs($user)
->withSession(['banned' => false])
->get('/');
//
});
actingAs の2つ目の引数にガード(ログインの確かめ方の名前)を渡すと、そのガードで認証します。そのガードは、テストが終わるまで、標準のガードにもなります。
$this->actingAs($user, 'web');
ログインしていない状態にしたいときは actingAsGuest を使います。
$this->actingAsGuest();
レスポンスの中身を調べる(デバッグ)#
テストのリクエストを送ったあと、dump・dumpHeaders・dumpSession で、レスポンスの中身を画面に出して調べられます。
<?php
test('basic test', function () {
$response = $this->get('/');
$response->dump();
$response->dumpHeaders();
$response->dumpSession();
});
中身を出したあとにそこで止めたいときは、dd・ddHeaders・ddBody・ddJson・ddSession を使います。
<?php
test('basic test', function () {
$response = $this->get('/');
$response->dd();
$response->ddHeaders();
$response->ddBody();
$response->ddJson();
$response->ddSession();
});
| 命令 | 説明 |
|---|---|
dump |
レスポンスの中身を出す |
dumpHeaders |
レスポンスのヘッダーを出す |
dumpSession |
セッションの中身を出す |
dd |
レスポンスの中身を出して止まる |
ddHeaders |
ヘッダーを出して止まる |
ddBody |
本文を出して止まる |
ddJson |
JSON を出して止まる |
ddSession |
セッションの中身を出して止まる |
例外(エラー)を確かめる#
アプリが特定の例外(エラーを知らせるしくみ)を出したかを確かめたいときは、Exceptions ファサードで例外の処理を「にせもの」に置きかえます(fake)。そのあと、assertReported と assertNotReported で、リクエスト中に出た例外を確かめます。
<?php
use App\Exceptions\InvalidOrderException;
use Illuminate\Support\Facades\Exceptions;
test('exception is thrown', function () {
Exceptions::fake();
$response = $this->get('/order/1');
// 例外が出たことを確かめる
Exceptions::assertReported(InvalidOrderException::class);
// 例外の中身も確かめる
Exceptions::assertReported(function (InvalidOrderException $e) {
return $e->getMessage() === 'The order was invalid.';
});
});
特定の例外が出ていないこと、またはどんな例外も出ていないことは、次のように確かめます。
Exceptions::assertNotReported(InvalidOrderException::class);
Exceptions::assertNothingReported();
あるリクエストだけ、例外の処理を完全に止めたいときは withoutExceptionHandling を使います。
$response = $this->withoutExceptionHandling()->get('/');
PHP や使っているライブラリが「もう古い」としている機能(非推奨)を、アプリが使っていないかを確かめたいときは withoutDeprecationHandling を使います。これを使うと、非推奨の警告が例外に変わり、テストが失敗します。
$response = $this->withoutDeprecationHandling()->get('/');
クロージャの中のコードが、決めた種類の例外を出すかは assertThrows で確かめます。
$this->assertThrows(
fn () => (new ProcessOrder)->execute(),
OrderInvalid::class
);
出た例外の中身まで調べたいときは、2つ目の引数にクロージャを渡します。
$this->assertThrows(
fn () => (new ProcessOrder)->execute(),
fn (OrderInvalid $e) => $e->orderId() === 123
);
クロージャの中のコードが、例外を1つも出さないことは assertDoesntThrow で確かめます。
$this->assertDoesntThrow(fn () => (new ProcessOrder)->execute());
JSON の API をテストする#
JSON(データを文字で表す形式)を返す API(プログラムどうしがやり取りする窓口)をテストするときは、json・getJson・postJson・putJson・patchJson・deleteJson・optionsJson を使います。データやヘッダーも渡せます。次は、/api/user に POST で送って、期待した JSON が返るかを確かめる例です。
<?php
test('making an api request', function () {
$response = $this->postJson('/api/user', ['name' => 'Sally']);
$response
->assertStatus(201)
->assertJson([
'created' => true,
]);
});
JSON の中身は、レスポンスを配列のように読んで取り出せます。
Pest のとき:
expect($response['created'])->toBeTrue();
PHPUnit のとき:
$this->assertTrue($response['created']);
補足
assertJson は、レスポンスを配列にして「渡した配列がその中にあるか」を調べます。ほかの項目が混ざっていても、渡した部分があれば成功します。
JSON がぴったり同じかを確かめる#
assertJson は一部が合っていれば通ります。渡した配列と JSON がぴったり同じかを確かめたいときは assertExactJson を使います。
<?php
test('asserting an exact json match', function () {
$response = $this->postJson('/user', ['name' => 'Sally']);
$response
->assertStatus(201)
->assertExactJson([
'created' => true,
]);
});
JSON のパス(道すじ)で確かめる#
JSON の中の決まった場所に、決まった値があるかは assertJsonPath で確かめます。場所は team.owner.name のように、ドットでつないで書きます。
<?php
test('asserting a json path value', function () {
$response = $this->postJson('/user', ['name' => 'Sally']);
$response
->assertStatus(201)
->assertJsonPath('team.owner.name', 'Darian');
});
値の代わりにクロージャを渡すと、その結果で成功か失敗かを決められます。
$response->assertJsonPath('team.owner.name', fn (string $name) => strlen($name) >= 3);
複数の場所をまとめて確かめるには assertJsonPaths を使います。値の代わりにクロージャも書けます。
$response->assertJsonPaths([
'team.owner.name' => 'Darian',
'team.owner.email' => fn (string $email) => str($email)->is('*@laravel.com'),
'team.members.0.name' => 'Sally',
]);
複数の場所が「無い」ことは assertJsonMissingPaths で確かめます。
$response->assertJsonMissingPaths([
'team.owner.password',
'team.members.0.api_token',
]);
流れるように JSON を確かめる(Fluent JSON テスト)#
assertJson にクロージャを渡すと、AssertableJson というオブジェクトを使って、メソッドをつないで確かめられます。where は項目の値を、missing は項目が無いことを確かめます。
use Illuminate\Testing\Fluent\AssertableJson;
test('fluent json', function () {
$response = $this->getJson('/users/1');
$response
->assertJson(fn (AssertableJson $json) =>
$json->where('id', 1)
->where('name', 'Victoria Faith')
->where('email', fn (string $email) => str($email)->is('victoria@gmail.com'))
->whereNot('status', 'pending')
->missing('password')
->etc()
);
});
etc メソッドの意味#
上の例の最後の etc は、「JSON にはほかの項目もあってよい」と Laravel に伝える命令です。etc が無いと、確かめていない項目が JSON にあるだけでテストが失敗します。
こうなっている理由は、うっかり秘密の情報を JSON に出してしまうのを防ぐためです。「1つずつ確かめる」か「ほかの項目があってもよいと etc で言う」かを、はっきり選ばせます。
ただし、etc を付けないことは、入れ子になった配列の中に項目が増えていないことまでは守りません。etc が確かめるのは、etc を書いた階層(入れ子の段)だけです。
項目の有る・無いを確かめる#
has は項目があること、missing は無いことを確かめます。
$response->assertJson(fn (AssertableJson $json) =>
$json->has('data')
->missing('message')
);
hasAll と missingAll は、複数の項目をまとめて確かめます。
$response->assertJson(fn (AssertableJson $json) =>
$json->hasAll(['status', 'data'])
->missingAll(['message', 'code'])
);
hasAny は、渡した項目のうち1つでもあれば成功します。
$response->assertJson(fn (AssertableJson $json) =>
$json->has('status')
->hasAny('data', 'message', 'code')
);
JSON の一覧(コレクション)を確かめる#
ルートが、ユーザーのような複数の項目を返すことがあります。
Route::get('/users', function () {
return User::all();
});
この場合は、has に数を渡して「3件ある」と確かめられます。first は、先頭の項目だけを確かめるためのクロージャを受け取ります。
$response
->assertJson(fn (AssertableJson $json) =>
$json->has(3)
->first(fn (AssertableJson $json) =>
$json->where('id', 1)
->where('name', 'Victoria Faith')
->where('email', fn (string $email) => str($email)->is('victoria@gmail.com'))
->missing('password')
->etc()
)
);
すべての項目に同じ確かめをしたいときは each を使います。
$response
->assertJson(fn (AssertableJson $json) =>
$json->has(3)
->each(fn (AssertableJson $json) =>
$json->whereType('id', 'integer')
->whereType('name', 'string')
->whereType('email', 'string')
->missing('password')
->etc()
)
);
名前の付いた一覧を確かめる#
一覧が、名前の付いたキーの中に入って返ってくることもあります。
Route::get('/users', function () {
return [
'meta' => [...],
'users' => User::all(),
];
});
has は、一覧の件数を確かめるのにも、確かめる範囲を絞るのにも使えます。
$response
->assertJson(fn (AssertableJson $json) =>
$json->has('meta')
->has('users', 3)
->has('users.0', fn (AssertableJson $json) =>
$json->where('id', 1)
->where('name', 'Victoria Faith')
->where('email', fn (string $email) => str($email)->is('victoria@gmail.com'))
->missing('password')
->etc()
)
);
has を2回呼ばなくても、3つ目の引数にクロージャを渡せば、1回で済みます。このクロージャは、一覧の先頭の項目の範囲で動きます。
$response
->assertJson(fn (AssertableJson $json) =>
$json->has('meta')
->has('users', 3, fn (AssertableJson $json) =>
$json->where('id', 1)
->where('name', 'Victoria Faith')
->where('email', fn (string $email) => str($email)->is('victoria@gmail.com'))
->missing('password')
->etc()
)
);
値の型を確かめる#
値そのものではなく「型」(文字列か数字かなど)だけを確かめたいときは、whereType と whereAllType を使います。
$response->assertJson(fn (AssertableJson $json) =>
$json->whereType('id', 'integer')
->whereAllType([
'users.0.name' => 'string',
'meta' => 'array'
])
);
型を | でつなぐか、配列で渡すと、どれか1つに当てはまれば成功します。
$response->assertJson(fn (AssertableJson $json) =>
$json->whereType('name', 'string|null')
->whereType('id', ['string', 'integer'])
);
使える型は次のとおりです。
| 型 | 説明 |
|---|---|
string |
文字列 |
integer |
整数 |
double |
小数 |
boolean |
真偽(true か false) |
array |
配列 |
null |
値が無いこと |
JSON を確かめる命令のまとめ#
| 命令 | 説明 |
|---|---|
where |
項目の値が合っているか |
whereNot |
項目の値が、渡した値ではないか |
missing |
項目が無いか |
missingAll |
複数の項目がすべて無いか |
has |
項目があるか。数やクロージャも渡せる |
hasAll |
複数の項目がすべてあるか |
hasAny |
渡した項目のどれかがあるか |
first |
一覧の先頭の項目を確かめる |
each |
一覧のすべての項目を確かめる |
whereType |
項目の型が合っているか |
whereAllType |
複数の項目の型が合っているか |
etc |
ほかの項目があってもよいと伝える |
ファイルのアップロードをテストする#
Illuminate\Http\UploadedFile の fake メソッドで、テスト用のにせのファイルや画像を作れます。Storage ファサードの fake と組み合わせると、アップロードのテストが簡単になります。次は、アバター(プロフィール画像)のアップロードを確かめる例です。
<?php
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
test('avatars can be uploaded', function () {
Storage::fake('avatars');
$file = UploadedFile::fake()->image('avatar.jpg');
$response = $this->post('/avatar', [
'avatar' => $file,
]);
Storage::disk('avatars')->assertExists($file->hashName());
});
ファイルが「無い」ことは、Storage の assertMissing で確かめます。
Storage::fake('avatars');
// ...
Storage::disk('avatars')->assertMissing('missing.jpg');
にせのファイルを細かく決める#
UploadedFile の fake で画像を作るとき、幅・高さ・サイズ(キロバイト)を決められます。バリデーション(送られてきた入力が正しいかのチェック)のルールを試すときに便利です。
UploadedFile::fake()->image('avatar.jpg', $width, $height)->size(100);
画像以外のファイルは create で作ります。
UploadedFile::fake()->create('document.pdf', $sizeInKilobytes);
必要なら、MIME タイプ(ファイルの種類を表す名前)も渡せます。
UploadedFile::fake()->create(
'document.pdf', $sizeInKilobytes, 'application/pdf'
);
ビューをテストする#
リクエストを送らずに、ビュー(画面の見た目を書いたファイル)だけを作って確かめることもできます。view メソッドに、ビューの名前と、あれば渡すデータを渡します。Illuminate\Testing\TestView が返り、中身を確かめる命令が使えます。
<?php
test('a welcome view can be rendered', function () {
$view = $this->view('welcome', ['name' => 'Taylor']);
$view->assertSee('Taylor');
});
TestView で使える命令は次のとおりです。
| 命令 | 説明 |
|---|---|
assertSee |
渡した文字が含まれる |
assertSeeInOrder |
渡した文字が、順番どおりに含まれる |
assertSeeText |
タグを除いた文章に、渡した文字が含まれる |
assertSeeTextInOrder |
タグを除いた文章に、渡した文字が順番どおりに含まれる |
assertDontSee |
渡した文字が含まれない |
assertDontSeeText |
タグを除いた文章に、渡した文字が含まれない |
TestView を文字列に変えると、できあがった HTML をそのまま取り出せます。
$contents = (string) $this->view('welcome');
エラーを渡す#
ビューによっては、入力チェックのエラーをまとめた入れ物(エラーバッグ)を使います。そのエラーを用意するには withViewErrors を使います。
$view = $this->withViewErrors([
'name' => ['Please provide a valid name.']
])->view('form');
$view->assertSee('Please provide a valid name.');
Blade の文字やコンポーネントを描く#
blade メソッドで、Blade の文字列をそのまま描いて確かめられます。view と同じく TestView が返ります。
$view = $this->blade(
'<x-component :name="$name" />',
['name' => 'Taylor']
);
$view->assertSee('Taylor');
Blade コンポーネントは component メソッドで描きます。こちらは Illuminate\Testing\TestComponent が返ります。
$view = $this->component(Profile::class, ['name' => 'Taylor']);
$view->assertSee('Taylor');
ルートをキャッシュする#
テストの前に、Laravel はアプリを新しく起動し、定義されたルートをすべて集めます。ルートのファイルが多いアプリでは、テストのクラスに Illuminate\Foundation\Testing\WithCachedRoutes トレイト(クラスに部品を足すしくみ)を足すとよいでしょう。ルートを1回だけ作ってメモリに置き、ほかのテストで使い回します。
<?php
use App\Http\Controllers\UserController;
use Illuminate\Foundation\Testing\WithCachedRoutes;
pest()->use(WithCachedRoutes::class);
test('basic example', function () {
$this->get(action([UserController::class, 'index']));
// ...
});
PHPUnit のときは、クラスの中で use WithCachedRoutes; と書きます。
<?php
namespace Tests\Feature;
use App\Http\Controllers\UserController;
use Illuminate\Foundation\Testing\WithCachedRoutes;
use Tests\TestCase;
class BasicTest extends TestCase
{
use WithCachedRoutes;
/**
* A basic functional test example.
*/
public function test_basic_example(): void
{
$response = $this->get(action([UserController::class, 'index']));
// ...
}
}
アサーションの一覧#
レスポンスのアサーション#
TestResponse には、たくさんの確認の命令があります。json・get・post・put・delete などが返すレスポンスに対して使います。ここでは種類ごとに分けて並べます。
ステータスコードを確かめる#
| 命令 | 説明 |
|---|---|
assertOk |
200(成功)である |
assertCreated |
201(作成した)である |
assertAccepted |
202(受け付けた)である |
assertNoContent |
内容が無く、決めた番号(初期値は 204)である |
assertMovedPermanently |
301(恒久的に引っ越した)である |
assertFound |
302(見つかった。転送)である |
assertBadRequest |
400(リクエストが不正)である |
assertUnauthorized |
401(ログインが必要)である |
assertPaymentRequired |
402(支払いが必要)である |
assertForbidden |
403(禁止)である |
assertNotFound |
404(見つからない)である |
assertMethodNotAllowed |
405(その種類のリクエストは許されない)である |
assertRequestTimeout |
408(リクエストが時間切れ)である |
assertConflict |
409(食い違いがある)である |
assertGone |
410(もう無い)である |
assertUnsupportedMediaType |
415(対応していない種類のデータ)である |
assertUnprocessable |
422(処理できない内容)である |
assertTooManyRequests |
429(リクエストが多すぎる)である |
assertInternalServerError |
500(サーバーの内部エラー)である |
assertServiceUnavailable |
503(いまは使えない)である |
assertFailedDependency |
424(前提の処理に失敗した)である |
assertStatus |
渡した番号のステータスコードである |
assertSuccessful |
200 以上 300 未満(成功の仲間)である |
assertClientError |
400 以上 500 未満(リクエスト側の誤り)である |
assertServerError |
500 以上 600 未満(サーバー側の誤り)である |
使い方はどれも同じです。たとえば次のように書きます。
$response->assertOk();
$response->assertStatus($code);
$response->assertNoContent($status = 204);
Cookie を確かめる#
| 命令 | 説明 |
|---|---|
assertCookie |
渡した名前(と値)の Cookie が含まれる |
assertCookieExpired |
その Cookie があり、期限が切れている |
assertCookieNotExpired |
その Cookie があり、期限が切れていない |
assertCookieMissing |
その Cookie が含まれない |
assertPlainCookie |
暗号化されていない Cookie が含まれる |
$response->assertCookie($cookieName, $value = null);
$response->assertCookieExpired($cookieName);
$response->assertCookieNotExpired($cookieName);
$response->assertCookieMissing($cookieName);
$response->assertPlainCookie($cookieName, $value = null);
本文やヘッダーを確かめる#
| 命令 | 説明 |
|---|---|
assertSee |
渡した文字が含まれる。ふつうは自動でエスケープする |
assertSeeInOrder |
渡した文字が、順番どおりに含まれる |
assertSeeText |
タグを除いた文章に、渡した文字が含まれる |
assertSeeTextInOrder |
タグを除いた文章に、渡した文字が順番どおりに含まれる |
assertDontSee |
渡した文字が含まれない |
assertDontSeeText |
タグを除いた文章に、渡した文字が含まれない |
assertContent |
本文が、渡した文字と同じである |
assertHeader |
渡したヘッダー(と値)がある |
assertHeaderContains |
ヘッダーの値に、渡した文字が含まれる |
assertHeaderMissing |
渡したヘッダーが無い |
assertDownload |
ダウンロードのレスポンスである |
assertStreamed |
ストリーム(少しずつ送る形)のレスポンスである |
assertStreamedContent |
ストリームの内容が、渡した文字と同じである |
assertSee などの文字を調べる命令は、渡した文字を自動でエスケープ(HTML で特別な意味を持つ記号を、ふつうの文字に直すこと)します。2つ目の引数に false を渡すと、エスケープしません。Text が付く命令は、PHP の strip_tags でタグを取りのぞいた文章を調べます。
$response->assertSee($value, $escape = true);
$response->assertSeeInOrder(array $values, $escape = true);
$response->assertSeeText($value, $escape = true);
$response->assertSeeTextInOrder(array $values, $escape = true);
$response->assertDontSee($value, $escape = true);
$response->assertDontSeeText($value, $escape = true);
$response->assertContent($value);
$response->assertHeader($headerName, $value = null);
$response->assertHeaderContains($headerName, $value);
$response->assertHeaderMissing($headerName);
$response->assertStreamed();
$response->assertStreamedContent($value);
assertDownload は、レスポンスがダウンロードかを確かめます。ふつうは、ルートが Response::download・BinaryFileResponse・Storage::download のどれかを返したときです。ダウンロードのファイル名も確かめられます。
$response->assertDownload();
$response->assertDownload('image.jpg');
リダイレクト(転送)を確かめる#
| 命令 | 説明 |
|---|---|
assertRedirect |
渡した URI への転送である |
assertRedirectBack |
前のページへ戻す転送である |
assertRedirectBackWithErrors |
前のページへ戻す転送で、セッションに渡したエラーがある |
assertRedirectBackWithoutErrors |
前のページへ戻す転送で、セッションにエラーが無い |
assertRedirectContains |
転送先の URI に、渡した文字が含まれる |
assertRedirectToRoute |
名前を付けたルートへの転送である |
assertRedirectToSignedRoute |
署名付きルート(改ざんを防ぐ印が付いた URL)への転送である |
assertLocation |
Location ヘッダーが、渡した URI である |
$response->assertRedirect($uri = null);
$response->assertRedirectBack();
$response->assertRedirectBackWithErrors(
array $keys = [], $format = null, $errorBag = 'default'
);
$response->assertRedirectBackWithoutErrors();
$response->assertRedirectContains($string);
$response->assertRedirectToRoute($name, $parameters = []);
$response->assertRedirectToSignedRoute($name = null, $parameters = []);
$response->assertLocation($uri);
JSON を確かめる#
| 命令 | 説明 |
|---|---|
assertJson |
渡した JSON のデータが含まれる |
assertExactJson |
渡した JSON のデータとぴったり同じである |
assertJsonFragment |
渡した JSON のデータが、どこかに含まれる |
assertJsonMissing |
渡した JSON のデータが含まれない |
assertJsonMissingExact |
渡した JSON のデータと同じものが含まれない |
assertJsonCount |
渡したキーの配列に、決めた数の項目がある |
assertJsonIsArray |
JSON が配列である |
assertJsonIsObject |
JSON がオブジェクト(名前と値の組)である |
assertJsonPath |
渡した場所に、期待した値がある |
assertJsonPaths |
渡した複数の場所に、期待した値がある |
assertJsonMissingPath |
渡した場所が無い |
assertJsonMissingPaths |
渡した複数の場所が無い |
assertJsonStructure |
渡した形(キーの並び)である |
assertExactJsonStructure |
渡した形とぴったり同じである |
$response->assertJson(array $data, $strict = false);
$response->assertExactJson(array $data);
$response->assertJsonCount($count, $key = null);
$response->assertJsonMissing(array $data);
$response->assertJsonMissingExact(array $data);
$response->assertJsonIsArray();
$response->assertJsonIsObject();
$response->assertJsonStructure(array $structure);
$response->assertExactJsonStructure(array $data);
assertJsonFragment は、JSON のどの深さにあっても見つけます。
Route::get('/users', function () {
return [
'users' => [
[
'name' => 'Taylor Otwell',
],
],
];
});
$response->assertJsonFragment(['name' => 'Taylor Otwell']);
assertJsonPath は、場所と期待する値を渡します。たとえば、次の JSON があるとします。
{
"user": {
"name": "Steve Schoger"
}
}
user の中の name を確かめるには、こう書きます。
$response->assertJsonPath('user.name', 'Steve Schoger');
複数の場所をまとめて確かめるときは assertJsonPaths を使います。
$response->assertJsonPaths([
'user.name' => 'Steve Schoger',
'user.email' => fn (string $email) => str($email)->endsWith('@laravel.com'),
]);
「無い」ことを確かめる assertJsonMissingPath と assertJsonMissingPaths は次のとおりです。
$response->assertJsonMissingPath('user.email');
$response->assertJsonMissingPaths([
'user.email',
'user.password',
]);
assertJsonStructure は、値ではなく形だけを確かめます。
$response->assertJsonStructure([
'user' => [
'name',
]
]);
次のように、オブジェクトの配列が返ることもあります。
{
"user": [
{
"name": "Steve Schoger",
"age": 55,
"location": "Earth"
},
{
"name": "Mary Schoger",
"age": 60,
"location": "Earth"
}
]
}
そのときは * を使うと、配列の中のすべてのオブジェクトの形を確かめられます。
$response->assertJsonStructure([
'user' => [
'*' => [
'name',
'age',
'location'
]
]
]);
assertExactJsonStructure は assertJsonStructure のきびしい版です。期待した形に書いていないキーがレスポンスにあると、失敗します。
セッションを確かめる#
| 命令 | 説明 |
|---|---|
assertSessionHas |
セッションに、渡したデータがある |
assertSessionHasInput |
一度だけ残した入力(フラッシュ入力)に、渡した値がある |
assertSessionHasAll |
セッションに、渡したキーと値の組がすべてある |
assertSessionMissing |
セッションに、渡したキーが無い |
assertSessionMissingInput |
一度だけ残した入力に、渡したキーが無い |
$response->assertSessionHas($key, $value = null);
$response->assertSessionHasInput($key, $value = null);
$response->assertSessionHasAll(array $data);
$response->assertSessionMissing($key);
$response->assertSessionMissingInput($key);
assertSessionHas と assertSessionHasInput の2つ目の引数には、クロージャも渡せます。クロージャが true を返すと成功します。
$response->assertSessionHas($key, function (User $value) {
return $value->name === 'Taylor Otwell';
});
use Illuminate\Support\Facades\Crypt;
$response->assertSessionHasInput($key, function (string $value) {
return Crypt::decryptString($value) === 'secret';
});
assertSessionHasAll は、キーと値の組をまとめて確かめます。
$response->assertSessionHasAll([
'name' => 'Taylor Otwell',
'status' => 'active',
]);
入力チェックのエラーを確かめる#
| 命令 | 説明 |
|---|---|
assertSessionHasErrors |
セッションに、渡したキーのエラーがある |
assertSessionHasErrorsIn |
名前の付いたエラーバッグの中に、渡したキーのエラーがある |
assertSessionHasNoErrors |
セッションに、エラーが1つも無い |
assertSessionDoesntHaveErrors |
セッションに、渡したキーのエラーが無い |
assertJsonValidationErrors |
JSON のエラーに、渡したキーのエラーがある |
assertJsonValidationErrorFor |
JSON のエラーに、渡したキーのエラーが何かある |
assertJsonMissingValidationErrors |
JSON のエラーに、渡したキーのエラーが無い |
assertValid |
入力チェックのエラーが無い(JSON でもセッションでも) |
assertInvalid |
入力チェックのエラーがある(JSON でもセッションでも) |
assertOnlyInvalid |
渡した項目だけにエラーがある |
$response->assertSessionHasErrors(
array $keys = [], $format = null, $errorBag = 'default'
);
$response->assertSessionHasErrorsIn($errorBag, $keys = [], $format = null);
$response->assertSessionHasNoErrors();
$response->assertSessionDoesntHaveErrors($keys = [], $format = null, $errorBag = 'default');
$response->assertJsonValidationErrors(array $data, $responseKey = 'errors');
$response->assertJsonValidationErrorFor(string $key, $responseKey = 'errors');
$response->assertJsonMissingValidationErrors($keys);
assertSessionHasErrors は、エラーがセッションに入る画面(フォーム)で使います。JSON で返す API では使いません。
$response->assertSessionHasErrors(['name', 'email']);
メッセージまで確かめたいときは、キーと文を渡します。
$response->assertSessionHasErrors([
'name' => 'The given name was invalid.'
]);
補足
assertSessionHasErrors と assertJsonValidationErrors は、エラーの返し方(セッションか JSON か)が決まっているときに使います。どちらでもよいときは、もっと広く使える assertInvalid がべんりです。これは、エラーが JSON で返ったときも、セッションに入ったときも調べます。逆に「エラーが無い」ことは assertValid で調べます。これは、JSON のエラーが無く、かつセッションにもエラーが入っていないことを調べます。
assertValid と assertInvalid の使い方です。
// 入力チェックのエラーがまったく無い
$response->assertValid();
// 渡したキーにエラーが無い
$response->assertValid(['name', 'email']);
// 渡したキーにエラーがある
$response->assertInvalid(['name', 'email']);
assertInvalid では、キーごとにメッセージも確かめられます。メッセージは全文でも、一部だけでもかまいません。
$response->assertInvalid([
'name' => 'The name field is required.',
'email' => 'valid email address',
]);
渡した項目だけにエラーがあることを確かめるときは assertOnlyInvalid を使います。
$response->assertOnlyInvalid(['name', 'email']);
ビューを確かめる#
| 命令 | 説明 |
|---|---|
assertViewIs |
ルートが、渡した名前のビューを返した |
assertViewHas |
ビューに、渡したデータがある |
assertViewHasAll |
ビューに、渡したデータがすべてある |
assertViewMissing |
ビューに、渡したキーのデータが無い |
$response->assertViewIs($value);
$response->assertViewHas($key, $value = null);
$response->assertViewHasAll(array $data);
$response->assertViewMissing($key);
assertViewHas の2つ目の引数にクロージャを渡すと、データの中身を調べられます。
$response->assertViewHas('user', function (User $user) {
return $user->name === 'Taylor';
});
ビューのデータは、レスポンスを配列のように読んでも取り出せます。
Pest のとき:
expect($response['name'])->toBe('Taylor');
PHPUnit のとき:
$this->assertEquals('Taylor', $response['name']);
assertViewHasAll は、キーだけでも、キーと値の組でも確かめられます。
$response->assertViewHasAll([
'name',
'email',
]);
$response->assertViewHasAll([
'name' => 'Taylor Otwell',
'email' => 'taylor@example.com,',
]);
ログインのアサーション#
ログインに関する命令もあります。これらは get や post が返すレスポンスではなく、テストのクラス自身に対して呼びます($this->)。
| 命令 | 説明 |
|---|---|
assertAuthenticated |
ログインしている人がいる |
assertGuest |
ログインしている人がいない |
assertAuthenticatedAs |
渡したユーザーがログインしている |
$this->assertAuthenticated($guard = null);
$this->assertGuest($guard = null);
$this->assertAuthenticatedAs($user, $guard = null);
入力チェックのアサーション#
入力チェックについては、主に2つの命令があります。送ったデータが正しかったか、まちがっていたかを確かめます。
| 命令 | 説明 |
|---|---|
assertValid |
渡したキーに、入力チェックのエラーが無い |
assertInvalid |
渡したキーに、入力チェックのエラーがある |
使い方は、上の「入力チェックのエラーを確かめる」と同じです。エラーが JSON で返ったときも、セッションに入ったときも使えます。
// エラーがまったく無い
$response->assertValid();
// 渡したキーにエラーが無い
$response->assertValid(['name', 'email']);
// 渡したキーにエラーがある
$response->assertInvalid(['name', 'email']);
// メッセージも確かめる(全文でも一部でもよい)
$response->assertInvalid([
'name' => 'The name field is required.',
'email' => 'valid email address',
]);
入力チェックそのものはバリデーションを見てください。
関連するページ#
公式ドキュメント(英語)
2026年10月5日時点の内容をもとに、日本語でまとめています。