2020-09-17

PHPのE2EテストでHTTPリクエストをモックする方法

背景

自動テストの文脈でアプリケーションが外部に対してHTTPリクエスト行う場合
一般的には以下のパターンで行うことが多いと思います。

ユニットテストの場合はアプリケーション的にHTTPクライアントをモックすることが多いと思いますが、 リモートホストに対してテストを行うE2Eテストだとアプリケーションサーバやモックサーバを立てる手法を取ることが多いと思います。

しかしながら、実際のアプリケーションサーバやテスト用のモックサーバを立てるのはやや面倒ですし
実用的にはテストを行うホストから適切にHTTPレスポンスをコントロールできるような調整も必要です。

そこで今回は php-vcr とauto_prepend_fileを使って E2Eテスト時の外部HTTPリクエストをモックする方法を紹介します。

方法

以下のようなPHPスクリプトを作成して、auto_prepend_fileに指定すれば
テスト側からphp-vcrのcassetteをコントロールしつつ外部HTTPリクエストをモックできます。

<?php

class MockHandler
{
    public function __construct($cassetteName)
    {
        // After turning on the VCR will intercept all requests
        \VCR\VCR::turnOn();
        
        // Record requests and responses in cassette file 'example'
        \VCR\VCR::insertCassette($cassetteName);
    }

    public function __destruct()
    {
        // To stop recording requests, eject the cassette
        \VCR\VCR::eject();
        
        // Turn off VCR to stop intercepting requests
        \VCR\VCR::turnOff();
    }
}

$cassetteName = $_SERVER['HTTP_X_VCR_CASSETTE'];
$_mockHandler = new MockHandler($cassetteName);

テストのHTTPリクエストのヘッダに X-VCR-CASSETTE を指定すればカセットをコントロールできるようになっています。
リモートホスト側にカセットファイルを置く必要はありますが、リクエストごとにカセットを指定することでHTTPレスポンスをコントロールできます。

まとめ

PHPアプリケーションに対するE2Eテストにおける外部HTTPリクエストのモック方法を紹介しました。
E2Eテストでカバレッジを取る方法のように、auto_prepend_fileを使うとテスト用の処理を自由に制御することができます。 もちろん、auto_prepend_fileのスクリプトに処理を書きすぎてテストの運用保守性が下がるのは避けたいところですが、
どうしてもテストがしづらいPHPアプリケーションに対してテストを書けるようにするアプローチとしては有効な手段だと思います。

このエントリーをはてなブックマークに追加