[Laravel]phpunitでRequestオブジェクトのmockを作成できない

カテゴリ: 未分類

Laravelでユニットテストをする際、(httpリクエストではなく)共通ライブラリのテストを行いたくて、Requestオブジェクトのモックを作りたい場合があります。

Mockeryを使って普通に作ると以下のうようにすれば良さそうですが、これは正しく動作しません。

use Illuminate\Support\Facades\Request;

class SomeTest extends TestCase
{

    public function testBasic()
    {
        // Requestのモックを作り、header()をコールしたら'hearer-value'を返すようにする
        Request::shouldReceive('header')
            ->once()
            ->andReturn('hearer-value');

        // requestのfeaderをコールしたら'hearer-value'が帰るはず... 
        //   (だが、このコードは正しく動かない)
        $value = request()->header('foo');
        $this->assertEquals('hearer-value', $value);
     }
}

実際に実行してみると、以下のようにsetUserResolver()の呼び出しがおかしいというエラーになります。

$ phpunit

PHPUnit 8.5.8 by Sebastian Bergmann and contributors.

There was 1 error:
Mockery\Exception\BadMethodCallException: 
   Received Mockery_1_Illuminate_Http_Request::setUserResolver(), 
   but no expectations were specified

正しく動作しない理由ですが、FacaceがRequestオブジェクトを生成する際に、その過程において内部でsetUserResolver()がコールされているのですが、setUserResolver()のモックを正しく作っていないためです。

RequestオブジェクトをMockで作ってはいけないことはLaravelの公式ドキュメントにも記載があります。

https://laravel.com/docs/8.x/mocking より

You should not mock the Request facade.
Instead, pass the input you desire into the HTTP helper methods such as get and post when running your test.
Likewise, instead of mocking the Config facade, call the Config::set method in your tests.

Requestファサードをモックしてはいけません。
その代わりテストを実行するときに、getやpostなどのHTTP helper methodsへ望む入力を渡してください。
同様に、Configのファサードをモックする代わりに、テストの中でConfig::set()メソッドを使ってください。

getやpostのヘルパーメソッドというのは、以下のようなlaravelのPHPUnitで使用できるヘルパメソッドのことで、Tests\TestCaseを継承することで使用できます。

use Tests\TestCase;

class SomeTest extends TestCase
{

    public function testBasic()
    {
        $this->get(...);
    }
}
こちらもおススメ

コメントを残す

メールアドレスが公開されることはありません。