経緯
LaravelでAPIサーバを開発中です。AWSのcodebuildでテストを走らせるためにテストのDBをMariaDBからSQLite3に変更しました。すると今まで通ってたテストが...失敗する...
Eloquentから取得したデータをJSON形式に整形して付き合わせしてるテストがことごとく失敗しています。どうやらint型が勝手にString型に変換されて返ってきてるようです。
現象
テストコード
// HogeModelのデータをHogeService経由で取得する場合のテストコード
public function testHoge()
{
$service = app(HogeService::class);
$ret = $service->getHogeData(1);
$ret = json_encode($ret, JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT);
$expected = trim(file_get_contents(__DIR__ . '/expect_05.json'));
$this->assertEquals($expected, $ret);
}
テスト結果のactual/expecteのDiff
@@ @@
"hoges": [\n
{\n
"id": 1,\n
- "other_id": 1,\n
+ "other_id": "1",\n
"label": "yes",\n
対応
調査1
記事の通り手元の環境でJSON_NUMERIC_CHECK
オプションをつけて実行してもやはりテストが完全に通らず。なおったりなおらなかったりってフワッとしてますね。
調査2
下記は、MariaDBでこういう現象が発生しなかったのはなぜだろうと調べて行き着いた記事です。
手元の環境で確認したところ
-
mysqlnd
が入っている -
PDO::ATTR_EMULATE_PREPARES
はtrue
ですので、mysql_pdoで自動型変換が抑制されていたようです。
対応策
DBによらず返す型は統一したいと考え、型キャストすることにしました。Laravelの$casts
プロパティを使ってHogeModelに下記コードを追加しました。
protected $casts = [
'id' => 'int',
'other_id' => 'int',
];
テスト通った!
まとめ
LaravelはほんとCoolだけど、PHPはまだちょっと好きになるには時間がかかりそう(オブラート)。少なくとも初心者がやるなら少なくともPHP以外をオススメするなあ...