<?php namespace Tests\Unit\MetadataResolver; use App\MetadataResolver\Resolver; use GuzzleHttp\Client; use GuzzleHttp\Handler\MockHandler; use GuzzleHttp\HandlerStack; use GuzzleHttp\Psr7\Response; use Monolog\Handler\AbstractHandler; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; trait CreateMockedResolver { /** * @var Resolver */ protected $resolver; /** * @var AbstractHandler */ protected $handler; /** * @var string */ protected $snapshotFilename; protected function fetchSnapshot(string $filename): string { $this->snapshotFilename = $filename; return file_get_contents($filename); } /** * @param string $resolverClass * @param string $responseText * @param array $headers * @param int $status * @return Resolver */ protected function createResolver(string $resolverClass, string $responseText, array $headers = [], int $status = 200) { if (!$this->shouldUseMock() && !$this->shouldUpdateSnapshot()) { $this->resolver = app()->make($resolverClass); return $this->resolver; } if ($this->shouldUseMock()) { $headers += [ 'content-type' => 'text/html', ]; $mockResponse = new Response($status, $headers, $responseText); $this->handler = new MockHandler([$mockResponse]); } $stack = HandlerStack::create($this->handler); $client = new Client(['handler' => $stack]); if ($this->shouldUpdateSnapshot()) { $stack->push($this->makeUpdateSnapshotMiddleware()); } $this->resolver = app()->make($resolverClass, ['client' => $client]); return $this->resolver; } protected function shouldUseMock(): bool { return (bool) env('TEST_USE_HTTP_MOCK', true); } protected function shouldUpdateSnapshot(): bool { return (bool) env('TEST_UPDATE_SNAPSHOT', false); } protected function makeUpdateSnapshotMiddleware(): callable { return function (callable $next) { return function (RequestInterface $request, array $options) use ($next) { return $next($request, $options)->then(function (ResponseInterface $response) { if (empty($this->snapshotFilename)) { throw new \RuntimeException('スナップショットのファイル名が分かりません。file_get_contents()を使っている場合、fetchSnapshot()に置き換えてください。'); } file_put_contents($this->snapshotFilename, (string) $response->getBody()); fwrite(STDERR, "Snapshot Updated: {$this->snapshotFilename}\n"); return $response; }); }; }; } }