はじめに
LaravelでassertJson
よりも「厳密」にテストができるというassertExactJson
を使っていて、どこでまで厳格なんだろう?時になったことのメモ
assertExactJsonの特徴
1,全データをテストできる
これはドキュメント見ての通り。
assertJson
は返ってきたjsonデータの内、一部のjsonフラグメントが返ってきているかテストできるメソッドであるのに対して
assertExactJson
は返ってきたjsonデータの構成や全フラグメントが完全に一致していることをテストできる
assertExactJson
はetc()
とか使わなくてよくなるし、確実に期待したjsonの構成として返却されていることがテストできる。
2,各フラグメントの一致具合も厳格にテストできる
コチラが本題。
例えばこんなjsonを返すControllerがあった場合
public function sample()
{
return response()->json([
'sample' => true,
]);
}
返ってくるjsonは以下になる
{
sample : true,
}
これをassertExactJson
でテストするとこうなる
protected function testSample()
{
// API呼び出し(routeの名前は仮)
$response = $this->getJson(route('sample'));
// jsonデータを配列に変換
$response->assertExactJson([
'sample' => true,
]);
}
結果は問題なくテストが通る
> php artisan test tests/Feature/Api/SampleTest.php
PASS Tests\Feature\Api\SampleTest
✓ sample
Tests: 1 passed
Time: 0.60s
ギモン
ここでギモンなのはここでいう一致は、通常の比較演算子(==)か厳格な比較演算子(===)のどちらを使っているか、ということ。
結論
結論は厳格な比較演算子(===)を使用している
厳密には「Jsonとしての文字列を比較している」というのが正しいです。
@nunulk 様ご指摘ありがとうございました。
以下は実際の検証ですので上記認識の状態で「ふーん、そんな結果になるんだ」程度に捉えてもらえるといいかと思います。
検証
もし通常の比較演算子(==)を使っていれば、テストの期待値をtrueではなく1にしても問題なくテストが通ることを想定できる。
dump(true == 1);
>> true
dump(true === 1);
>> false
そこで先ほどのテストで引数(=期待値)を1にする
protected function testSample()
{
// API呼び出し(routeの名前は仮)
$response = $this->getJson(route('sample'));
// jsonデータを配列に変換
$response->assertExactJson([
'sample' => 1, // 変更
]);
}
結果、テストは失敗する
> php artisan test tests/Feature/Api/SampleTest.php
FAIL Tests\Feature\Api\SampleTest
⨯ sample
---
• Tests\Feature\Api\SampleTest > sample
Failed asserting that two strings are equal.
at tests/Feature/Api/SampleTest.php:94
90▕ $response = $this->getJson(route('sample'));
91▕
93▕ $response->assertExactJson([
➜ 94▕ 'success' => 1,
95▕ ]);
--- Expected
+++ Actual
@@ @@
-'{"success":1}'
+'{"success":true}'
Tests: 1 failed
Time: 0.51s
これで厳格な比較演算子でテストしていることが検証できた
おわりに
型が違うのにテストを通してしまうのは怖いことだな、と感じた。
assertExactJson
にて通常の比較演算子(==)を使っていないことを知り、安心