LoginSignup
3

More than 5 years have passed since last update.

PHP & Phake で static なモックを「副作用」なく使用する方法

Last updated at Posted at 2016-03-19

Static なメソッド呼び出しにモックを適用したい。でも PHPUnit や Mockery で static なモックを設定すると、他クラスで当該メソッドが読み込まれた場合にエラーが発生してしまう。。。
このようなジレンマを克服するために、PHP の OSS のモックフレームワークの Phake を使用して、上述の課題を克服する方法を説明します。

説明の前提条件

  • モックを適用する対象は、APIクラスのrequest()メソッドとします。
  • request()メソッドは、static とします。
  • request()メソッドの引数には、任意の値を指定できることとします。
  • request()メソッドは、基本的に以下のように呼び出されるものとします。
    API::request($hoge);
  • APIクラスのrequest()メソッドを使用している SUT(テスト対象)は、SUTクラスとします。

1. SUT の修正手順

1) APIを、クラス変数として定義する

    private static $api;

2) コンストラクタで、API変数を初期化する

    function __construct() {
        self::$api = new API();
    }

3) API変数用の setter を用意する

    public function set_API($arg) {
        self::$api = $arg;
    }

DI(Dependency Injection)の、特に setter injection の手法を採用しています。
これにより、テストケースで static なモックを設定することが可能になります。

4) request()メソッドの呼び出し箇所を、API変数を使用する方法に変更する

    // self::$api::request() という表記は出来ない模様。
    self::$api->request($hoge)

上記 2) と合わせ、モックをセットしていない場合(=通常呼び出し時)は、これまで通りAPI::request()と同じ挙動をすることになります。
また、モックをセットしている場合は、セットしたモックが呼ばれることになります。

2. テストケースの作成手順

1) tearDown()メソッドを定義し、Phake::resetStaticInfo()を呼び出すようにする

    public function tearDown() {
        Phake::resetStaticInfo();
    }

これにより、各テストケース実行の度に static なモックの設定がリセットされるため、他クラスで当該メソッドが読み込まれた場合にエラーが発生することを予防できます。

2) static なモックを定義する

$mock = Phake::mock('API');

// 引数が毎回異なる前提なので、Phake::anyParameters() メソッドを使用しています。
// また、戻り値の変数 $return は、予め定義してあるものとします。
Phake::whenStatic($mock)->request(Phake::anyParameters())
    ->thenReturn($return);

// request() メソッドがキチンと1回だけ呼び出せていることの検証です。
Phake::verifyStatic($mock, Phake::times(1))->request(Phake::anyParameters());

Phake の各メソッドの後ろに Static とつけることで、static なモックとして定義できます。

3) static なモックを SUT にセットする

    $sut = new SUT();
    $sut->set_API($mock);

    // テスト対象メソッドを呼び出します。
    $sut->xxx();

これで、SUT に先に設定した setter injection との合わせ技で、Phake で static なモックを「副作用」なく使用することができるようになりました。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3