Guzzleを使ってAPIのテストを書く

概要

DBの単体テストは、PHPUnitを使うことで手軽に行うことができていました。
しかし、APIのテストはやり方がわかっておらず、テストコードの作成を行えていませんでした。

今回Guzzleを使って、モックを差せることがわかったので、実践したやり方をまとめてみます。

実践

本体

コードを書くときに、コンストラクタ内でオブジェクト生成するのではなく、外から生成したオブジェクトを渡すようにしました。
こうすることで、テストコードでモックを差すことができるからです。

class Hoge
{
    private $client;
    private $url;
    
    public function __construct(HttpClient $client, string $url)
    {
        $this->client = $client;
        $this->url = $url;
    }
    
    public function getList(string $channelId)
    {
        $response = $this->client->request(
            'POST',
            $this->url,
            [
                'headers' => [
                    'Content-Type'  => 'application/json',
                    'x-sora-target' => https://hoge.com/hogehoge,
                ],
            ]
        );
        return \GuzzleHttp\json_decode($response->getBody(), true);
    }
}

テストコード

次にテストコードです。
テストにはPHPUnitを使います。

最初に期待するAPIのレスポンスをResponseクラスを使って生成します。
次にそのResponseクラスを使って、handlerを生成します。 これをコードに渡してあげることで、APIリクエストを行う際に、モックから実行結果を受け取ってくれます。

こうすることで、APIのテストをモックを使って行うことができました。

class HogeTest extends TestCase
{
    /**
     * @test
     */
    public function testGetClientList()
    {
        $channelId = 'test';
        $mockResponse = new Response(200, [],
            json_encode(レスポンス)
        );
        $mock = new MockHandler([$mockResponse]);
        $handler = HandlerStack::create($mock);
        $mockClient = new HttpClient([
            'handler' => $handler,
        ]);
        $client = new Hoge($mockClient, 'http://localhost/');
        $actual = $client->getList($channelId);
        }
    }
}

ちなみに複数のレスポンスをモックで刺したい場合は、MockHandlerを生成するところで、複数渡せばOKです。

$mock = new MockHandler([$mockResponse, $mockResponse$]);

まとめ

Guzzleを使うことで、APIのテストコードを書くことができました。
こうすると、CIでAPIのテストも回す事ができますね。

注意しなければいけないのは、APIの振る舞いが変わったときに、モックも修正しなければいけないということです。
そうしないと、デプロイしたときにエラーが出てしまいます。