LoginSignup
2
1

More than 3 years have passed since last update.

【PHPUnit】モックした関数の返り値を引数を元に求めるにはandReturnUsingを使う

Last updated at Posted at 2020-03-12

背景

PHPUnit を使っていると、関数をモックにしたい場面があります。
一般には下記のように実装します。

Mockery::mock('class name')->shouldReceive('method')->withArgs($param)->andReturn($returnValue);

こういった書き方では返り値が決め打ちになっています。
ほとんどの場面では、返り値は固定値で問題ないはずですが、今目の前で、動的に返り値が決まっていたほうが都合がいい場面が起こったので調べてみました。

andReturnUsingを利用する

ありました。andReturnUsingという関数を使えばいいです。

書き方はコールバックを受け取り、コールバックの引数をモック化したい関数の引数と同じにします。
あとはそのコールバックの返り値を計算してreturnするだけで返り値を指定できます。

Mockery::mock('class name')
    ->shouldReceive('method')
    ->withArgs(function ($params1, $params2) {
        // $paramsを使った処理・・・
        return true;
    })
    ->andReturnUsing(function ($params1, $params2) {
        // $paramsを使った処理・・・
        return $calculateResult;
    }
);

実例

ユースケースの中で、別のエンドポイントに通信して、得た結果で引き続き処理をするというものがありました。この場合は通信自体モックにするのがベターですが、どうしても通信先の処理も結合テストしたかったので、まとめてテストできるようにテストを書きました。

$clientMock = Mockery::mock(Client::class);
$clientMock->shouldReceive('post')
    ->withArgs(function (string $uri, array $data) {
        // 省略
        return true;
    })->andReturnUsing(function (string $uri, array $data) {
        $response = $this->post('{テストしたいエンドポイント}', $data['form_params']);
        $mock = Mockery::mock('TestResponse');
        // GuzzleのResponse Interfaceをモック
        $mock->shouldReceive('getStatusCode')->andReturn(200);
        $mock->shouldReceive('getBody')->andReturn(json_encode($response->json()));
        return $mock;
    });
$this->app->instance(Client::class, $clientMock);

こうすると、andReturnUsingの中で、$this->postで実際の通信処理が走るので、別のエンドポイントの動作チェックも兼ねることができます。

また、引数で$data['form_params']を渡すことで、引数が正しく渡っていることがテストできます。

繰り返しますが、本当はこういった場合は個別にテストを書いたほうがいいですね。

2
1
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1