PHP

PHPUnitのモックオブジェクトの使い方を仕組みから理解する

投稿日:2016年12月12日 更新日:


前回はPHPUnitのメイン処理を確認しました。今回はPHPUnitデフォルトのモックオブジェクトの仕組みを確認してみます。公式ドキュメントでは、第9章 テストダブルが該当箇所となります。

20161019203514

PHPUnitのモックオブジェクトについて

PHPUnitは以下のような構成ですが、その中の「phpunit-mock-objects」がPHPUnitデフォルトのモックライブラリとなります。

  • phpunit
    • php-code-coverage
    • php-file-iterator
    • php-text-template
    • php-timer
    • php-token-stream
    • phpunit
    • phpunit-mock-objects ← これ

構成

PHPUnitモックオブジェクトのファイル構成は以下の通りです。

今回は中でも主要処理のあるGenerator、MockBuilder、InvocationMockerをチェックしました。

スタブとモックオブジェクトについて

モックオブジェクトを確認する前に、スタブとモックオブジェクトについて簡単に整理しておきます。PHPUnitの公式ドキュメントでは以下のように記載しています。

スタブ

実際のオブジェクトを置き換えて、 設定した何らかの値を (オプションで) 返すようなテストダブルのことを スタブ といいます。

モックオブジェクト

実際のオブジェクトを置き換えて、 (メソッドがコールされたことなどの) 期待する内容を検証するテストダブルのことを モック といいます。

違いがちょっとわかりにくいですが、スタブもモックオブジェクトもテストの為の代用品(テストダブル)であることに変わりはありません。では何が違うのか。それは使われ方によって変わってきます。(※個人的な見解も含んでいます。)

テストをする際には、必要に応じてオブジェクトをモック化する必要があり、その際メソッドを握りつぶし何らかの振る舞いを設定するのですが、そのテストの代用品自体がスタブとなります。モックオブジェクトは、モック化したスタブオブジェクトをテスト対象クラスに差し込み、差し込んだモックオブジェクトが想定通り使われているかを確認する為に使うことでモックオブジェクトとなります。

言葉だけだとイメージしにくいので図にしてみました。

スタブ
%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-12-14-10-59-32

モックオブジェクト
%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-12-12-18-37-26

モック化したオブジェクトをスタブと呼ぶかモックと呼ぶかはいまいちはっきりわからなかったので以下ではモックと統一して進めていきます。

モックの使い方

では具体的なモックの使い方を確認してみます。

20161024204138

PHPUnitのTestCaseクラスはモックの呼び出し処理をいくつかラップしているのでTestCaseを継承していればモックを利用することができます。

PHPUnitのモックの呼び出しは大きく以下の3つの方法があります。

  • 自分で1からプロパティを設定してモックを作成する「getMockBuilder」を使う方法
  • 予めプロパティを設定されたモックを取得する「createMock」を使う方法
  • モック化したいクラス名とプロパティ情報を引数で渡してモックを生成する「getMock」を使う方法(※現在非推奨)

その中でも普通に使う分には「createMock」を使う方法が一番楽で良いかと思います。ただこの場合コンストラクタが呼ばれないので、コンストラクタを呼びたい場合や他に設定を変えたい場合は「getMockBuilder」を使ってモック化を行います。

createMockの処理を簡単に確認する

createMock

  • getMockBuilderでモックを取得
  • 必要なプロパティをメソッドチェーンで設定する
  • MockBuilderはGeneratorを使って自身のプロパティを渡しモックを生成する
    ※ createMockを使う場合コンストラクタ含め例外を除く全メソッドが握りつぶされます。

createPartialMock

createPartialMockをいうメソッドも用意されているので見てみます。これは指定したメソッドだけを握りつぶすことができます。指定しない場合は全て元のまま呼び出せます。

createConfiguredMock

createConfiguredMockも一応見てみると、これはcreateMock+メソッドの振る舞い設定の組み合わせのfunctionです。

モック生成の具体例

実際にcreateMockとcreatePartialMockを使ったモック生成方法を以下の例を使って確認してみます。

テスト対象のクラス例

何でもない変なクラスですが一応補足しておくと確認しやすいように以下のメソッドを用意しています。

  • ただ処理するだけのメソッド
  • クラス内のgetterを呼び出して処理しているメソッド
  • クラス内のsetterを呼び出して処理しているメソッド
  • privateメソッド
  • staticメソッド

createMockで全モック

コンストラクタは呼ばれず全てのメソッドは握りつぶされます。その状態でメソッドを呼び出しても結果は取得できません。

イメージ
全部呼び出せない。
%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-12-15-20-42-52

createMockで振る舞い設定

イメージ
plusAだけ呼び出せて(実態はよばれない)結果は自分の設定した値になる。
%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-12-15-20-59-27

createPartialMockで部分モック

第一引数に対象のクラスと第二引数に握りつぶしたいメソッドを配列で指定すると部分的にモック化することができる。第二引数を指定しない場合(または空の配列を指定)すべてのメソッドは元のまま。

イメージ
一部握りつぶし他は元のまま
%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-12-15-21-09-15

振る舞いを指定する場合は以下のようにする

イメージ
一部握りつぶし振る舞いを設定し他は元のまま
%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-12-15-21-07-59

また、setterのようにどの引数で何回呼ばれたかを確認するには以下のように書きます。

モックの振る舞いを設定する処理について

最後にモックに振る舞いを設定する処理について簡単に触れておきます。モックの振る舞いを設定する処理はInvocationMockerクラスが担っていて、method、willReturn、expects、withなどを使って振る舞いや期待値を設定します。

20161024204136

method

振る舞いや期待値を設定するメソッドを指定する

willReturn

スタブメソッドにどのような値を返させるかを設定する

expects

スタブメソッドが何回呼ばれるかを設定する

with

スタブメソッドがどの引数を受け取るかを設定する

カバレッジレポート

これらのテストのカバレッジレポートを出力します。カバレッジレポートは以下のように出力することができます。サンプルソースはこちらにあります。

出力方法

カバレッジレポート

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-12-16-17-25-14

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-12-16-17-25-34

コンストラクタとprivateとstaticとgetTotalメソッドはテストを通していないので赤く塗られます。また、privateとstaticメソッドのモック化やテストは面倒なので別のモッキンフレームワークであるPhakeなどでやったほうがいいと思います。

これで大体のモック仕組みとの基本の使い方の確認の確認ができました。これらを使って組み合わせるだけでも多くのテストの実行がカバーできるかと思います。

今回使ったPHPUnitのバージョン

“phpunit/phpunit”: “5.6.*”


-PHP
-, , , ,

執筆者:

関連記事

PHPのモッキンフレームワークPhakeの使い方

前回に引き続きPHPUnit関連の記事です。今回はPHPのモッキンフレームワークであるPhakeの使い方を確認します。 Phakeについて 作者は? Mike Livelyという方のようです。 twi …

PHPUnitの使い方を仕組みから理解する

ここ数年仕事ではPHPを使って開発をしていますが、最近品質について考える機会が増えたこともあり、これを機にPHPUnitと周辺のモジュールの仕組みを理解してより楽にテストができるようにしたいと思います …