環境: Laravel 5.6
Laravel5系では、発行されたSQLを以下の手順で確認できます。
DB::connection()->enableQueryLog();
- データベースアクセスのメソッドを実行する。
DB::getQueryLog();
これを使ってPHPUnitでRepository層のテストを書くことが目標です。
例として、指定したUserIdで直近2週間の記事一覧を返すメソッドのテストを実装します。
サンプルのテストコード
public function testQueryTest()
{
$article = new Article; //Eloquent Model
$repository = new ArticleRepository($article);//コンストラクタイジェクション
DB::connection()->enableQueryLog();
$repository->listById(1);
$queries = DB::getQueryLog();
$this->assertEquals(
$queries[0]['query'],
"select * from `articles` where `user_id` = ? and `created` >= ?"
);
$this->assertEquals(
$queries[0]['bindings'],
[
0 => "1",
1 => "2018-09-17 00:00:00"]
);
}
テストを実行
vendor/bin/phpunit --filter=testQueryTest
OK (1 test, 2 assertions)
解説
上記サンプルで$queryies
をdumpするとこのようなデータが得られるので、assertEqualsに突っ込んでます。
array:1 [
0 => array:3 [
"query" => "select * from `articles` where `user_id` = ? and `created` >= ?"
"bindings" => array:2 [
0 => 1
1 => "2018-09-17 00:00:00"
]
"time" => 25.52
]
]
感想
DBアクセス層の仕様を表現するには生のSQL以上のものはないので、明快なUnitテストが書けました。また、テストコードにはWhatを記載せよとの教えの通り、ドキュメントとしての役割も持たせられたと思います。
ただ、これを全Repositoryのテストに導入するぞ!となったら作業コストやパフォーマンス面が心配です。
主にデバッグ用途に使って、変更が多い機能や、サービスのコアになる複雑な機能には導入すると安全なのかなと思いました。