Mockery をテストしているとやっているときに配列やオブジェクトを使っているとNoMatchingExpectationException
が出てきたときにどこが問題だかわからなくなる場合があります。
$this->guzzleClient = Mockery::mock(ClientInterface::class);
$requestResponse = $this->client->request('POST', $apiUrl, ['form_params' => $params]);
$this->guzzleClient
->shouldReceive('request')
->once()
->with('POST',
'http://test.example.com/article/xxxx/comments',
['form_params' => $params])
->andReturn($response);
Mockery\Exception\NoMatchingExpectationException: No matching handler found for Mockery_0_GuzzleHttp_ClientInterface::request('POST', 'http://test.example.com/article/xxxx/comments', ['form_params' => [...]]). Either the method was unexpected or its arguments matched no expected argument list for this method
こういうとき、どの引数が一致せずにエラーが出るのかよくわからなくなります。
なので anyな引数を許可して実行してみることが大事です。
解決法: こんなときは Mockery::on を使ってすべての引数を許可する形にしてしまう。
どの引数が原因だかわからないときは、とりあえずエラーが出ずに動くようにすることを優先すると特定が早まった.
$this->guzzleClient = Mockery::mock(ClientInterface::class);
$requestResponse = $this->client->request(
Mockery::on(function($actual) {
return true;
}),
Mockery::on(function($actual) {
return true;
}),
Mockery::on(function($actual) {
return true;
})
);
例えば、弄っているうちに原因が第三引数にあることがわかったので下記のように修正すると↓
最終形はこんなの
$form_params = ['form_params' => $params];
$this->guzzleClient = Mockery::mock(ClientInterface::class);
$requestResponse = $this->client->request(
'POST',
$apiUrl,
Mockery::on(function($actual) {
return is_array($actual) && arrayHasKey($actual,'form_params') && is_array($actual['form_params']);
})
);
参考文献:
- 検索時に一番上に出てくるやつ: object.equals を受けてる
- 謎の判定の厳密比較されているarrayのやつ(どこでついたかわからないPHP_EOLが必要):
- そもそもMockery::onを使って判定をスルーする方法。
- 引数の数を確かめるのも大事
その他
上記はチームメンバーの問題解決に口出ししただけなので、自分の手元で動かして動作確認してないことに注意