Instantly share code, notes, and snippets.

Embed
What would you like to do?
php-vcrを使いやすくするためのtrait
<?php
namespace src\Tests\Support;
use VCR\Request;
use VCR\VCR;
/**
* Trait VcrTrait
*/
trait VcrTrait
{
/**
* php-vcrを簡単に使えるようにするもの
* @see https://github.com/php-vcr/php-vcr
*
* 使い方
*
* 引数のcallbackにAPI通信を伴う処理を入れて、cassettePathとcassetteName(デフォルトではymlファイル)を指定する
* そうすると'cassettePath/cassetteName'が作られ、同じリクエスト内容であれば次回以降はこのファイルが参照される
*
* 例
*
* use VcrTrait;
* $response = $this->useCassette(function () {
* return $apiClient->apiRequest();
* }, 'cassettePath', 'cassette_name.yml');
*
* 注意
*
* $requestMatchersにheadersが指定されていた場合は実行環境に依存する値を気にしないようにしている
* 個々の環境でcurlのバージョンなどが異なる等の理由でテストが落ちることがあるため
*
* @param $callback
* @param $cassettePath
* @param $cassetteName
* @param string $storage
* @param array $libraryHooks
* @param array $requestMatchers
* @param null $mode
*
* @return mixed
*/
private function useCassette(
$callback,
$cassettePath,
$cassetteName,
$storage = 'yaml',
array $libraryHooks = ['curl', 'stream_wrapper'],
array $requestMatchers = [
'method',
'url',
'headers',
'host',
'body',
'post_fields',
'query_string'
],
$mode = null
) {
if (!is_dir($cassettePath)) {
mkdir($cassettePath);
}
VCR::configure()->setCassettePath($cassettePath);
VCR::configure()->setStorage($storage);
VCR::configure()->enableLibraryHooks($libraryHooks);
$requestMatchers = $this->getRequestMatchersIgnoredDependence($requestMatchers);
VCR::configure()->enableRequestMatchers($requestMatchers);
if ($mode) {
VCR::configure()->setMode($mode);
}
VCR::turnOn();
VCR::insertCassette($cassetteName);
$result = call_user_func($callback);
VCR::eject();
VCR::turnOff();
return $result;
}
/**
* headerのmatch時に実行環境に依存する項目を除く
* 実行環境に依存しないheadersが合っていた場合にtrueを返す
*
* @return \Closure
*/
private function matchHeadersIgnoredDependence()
{
return function (Request $first, Request $second) {
$firstHeadersIgnoredUA = $first->getHeaders();
unset($firstHeadersIgnoredUA['User-Agent']);
unset($firstHeadersIgnoredUA['Authorization']);
$secondHeadersIgnoredUA = $second->getHeaders();
unset($secondHeadersIgnoredUA['User-Agent']);
unset($secondHeadersIgnoredUA['Authorization']);
return array_filter($firstHeadersIgnoredUA) === array_filter($secondHeadersIgnoredUA);
};
}
/**
* $requestMatchersにheadersが含まれていた場合は、実行環境に依存しないheadersを対象にする
* @see http://php-vcr.github.io/documentation/configuration/#request-matching
*
* @param array $requestMatchers
*
* @return array
*/
private function getRequestMatchersIgnoredDependence(array $requestMatchers)
{
if (in_array('headers', $requestMatchers)) {
$requestMatchers = array_diff($requestMatchers, ['headers']);
VCR::configure()->addRequestMatcher('headers_ignore_ua_matchers', $this->matchHeadersIgnoredDependence());
$requestMatchers[] = 'headers_ignore_ua_matchers';
}
return $requestMatchers;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment