概要
- laravelにてMockeryを用いてDBへの問い合わせ処理部分のリポジトリインターフェースの関数の戻り値設定を行ったが何を設定してもnullが帰ってきてしまう問題の原因がわかったのでまとめる。
原因
- Mockeryで戻り値を指定しているリポジトリインターフェースの関数の戻り値指定がvoidになっていた。
各種クラス
-
使用しているコードをかなり簡素化して記載する。(このままコピペしても動作しないので注意)
-
モック化したいリポジトリインターフェースクラスと関数
FooRepositoryInterface.php<?php interface FooRepositoryInterface { public function update(Foo $foo): void; }
-
テストコードによるモック化処理と戻り値設定
Unit/FooTest.php<?php class FooTest extends TestCase { public function setUp(): void { parent::setUp(); $this->FooRepository = Mockery::mock(FooRepositoryInterface::class); } public function test_何かしらのチェック(): void { // FooRepositoryInterfaceのupdate関数を実行した際、引数に関係なく「true」を返すようにMockeryを設定 $this->FooRepository ->shouldReceive('update') ->andReturn(true); // アサーションによるチェック処理 }
細かい原因
-
FooRepositoryInterface.phpのupdateの戻り値のタイプヒンティング(型宣言)にてvoidが指定されてしまっていることが問題だった。
-
Mockeryは当該のリポジトリインターフェースクラスを元にモックを設定している。
-
テストコード側のsetUp()関数でリポジトリインターフェースを元に生成したモックをプロパティーに登録している。
Unit/FooTest.phppublic function setUp(): void { parent::setUp(); $this->FooRepository = Mockery::mock(FooRepositoryInterface::class); }
-
-
なのでいくら戻り値の設定をテスト関数無いで設定しても、もともとのリポジトリインターフェースの戻り値のタイプヒンティングの設定が勝ってしまい、戻り値を設定しても何も帰ってこない。
-
ようは今回はモック化したい関数そのものの意図に反する戻り値をモックで設定してしまった。(本来戻り値がvoidの関数をモックで戻り値がtrueになるように設定)
-
どうしてもモックの戻り値設定を生かしたいなら下記のようにリポジトリインターフェースの当該関数の戻り値のタイプヒンティングのvoidを消せば良い。(ただこれだと根本解決になっていないのであくまで問題の切り分け用としての確認方法になる。)
FooRepositoryInterface.php<?php interface FooRepositoryInterface { public function update(Foo $foo); }