laravelのテストでは、assertJson
メソッドを使ってAPIのレスポンスを検証できるようになっています。
例えば、routes/api.php
に以下のようなエンドポイントを定義したとき
Route::get('/test', function (Request $request) {
return response()->json([
'message' => 'ok',
]);
});
レスポンスはこのように検証することができます。
class ExampleTest extends TestCase
{
public function testBasicTest(): void
{
$response = $this->get('/api/test');
$response->assertJson([
'message' => 'ok',
]);
}
}
テストを実行するとこのように通ります。
PHPUnit 9.5.4 by Sebastian Bergmann and contributors.
Time: 00:00.253, Memory: 30.00 MB
OK (1 test, 1 assertion)
次に、ユーザーがログインしている時だけ追加のプロパティが返るようなエンドポイントを考えます。
Route::get('/test', function (Request $request) {
$response = ['message' => 'ok'];
if ($request->user()) {
$response['logged in'] = true;
}
return response()->json($response);
});
テストコードは先ほどと同じです。ユーザーはログインしていないので、logged in
プロパティは含まれないはずです。
class ExampleTest extends TestCase
{
public function testBasicTest(): void
{
$response = $this->get('/api/test');
$response->assertJson([
'message' => 'ok',
]);
}
}
テストも通ります。何も問題なさそうに見えます。
PHPUnit 9.5.4 by Sebastian Bergmann and contributors.
Time: 00:00.253, Memory: 30.00 MB
OK (1 test, 1 assertion)
では、ここでエンドポイントの定義をこのように変更してみます。ログインしているかに関わらず、logged in
プロパティをセットするように変更しました。
Route::get('/test', function (Request $request) {
$response = ['message' => 'ok'];
// if ($request->user()) {
$response['logged in'] = true;
// }
return response()->json($response);
});
この状態でテストを走らせるとどうなるでしょうか?
なんと、テストは通ってしまいます。
PHPUnit 9.5.4 by Sebastian Bergmann and contributors.
Time: 00:00.273, Memory: 30.00 MB
OK (1 test, 1 assertion)
何故テストが通ってしまうのか、その答えはassertJson
メソッドのコメントに書いてあります。
Assert that the response is a superset of the given JSON.
直訳すると「レスポンスがJSONのスーパーセットになっているかを表明します」。つまりこのメソッドは、レスポンスが引数の配列を内包していることを確かめるだけで、余分なプロパティが含まれていないことまでは確かめられないのですね。
PHPUnit 9.5.4 by Sebastian Bergmann and contributors.
Failed asserting that two strings are equal.
Expected :'{"message":"ok"}'
Actual :'{"logged in":true,"message":"ok"}'
ではどうするか、ですがlaravelにはassertExactJson
という素晴らしいメソッドがあります。このメソッドはレスポンスと引数の配列が厳密に一致することを確かめてくれます。
レスポンスに余分なプロパティが含まれていないこと、を検証する場合はこちらのメソッドを使いましょう。