Posted on

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

前回に引き続きPHPUnit関連の記事です。今回はPHPのモッキンフレームワークであるPhakeの使い方を確認します。
20161019203514

Phakeについて

作者は?

Mike Livelyという方のようです。

Phakeって?

こちらですね。

ファイル構成

一応ファイル構成を載せておきます。

.
├── Phake
│   ├── Annotation
│   │   ├── MockInitializer.php
│   │   └── Reader.php
│   ├── CallRecorder
│   │   ├── Call.php
│   │   ├── CallExpectation.php
│   │   ├── CallInfo.php
│   │   ├── IVerificationFailureHandler.php
│   │   ├── IVerifierMode.php
│   │   ├── OrderVerifier.php
│   │   ├── Position.php
│   │   ├── Recorder.php
│   │   ├── Verifier.php
│   │   ├── VerifierMode
│   │   │   ├── AtLeast.php
│   │   │   ├── AtMost.php
│   │   │   ├── Result.php
│   │   │   └── Times.php
│   │   └── VerifierResult.php
│   ├── ClassGenerator
│   │   ├── EvalLoader.php
│   │   ├── FileLoader.php
│   │   ├── ILoader.php
│   │   ├── InvocationHandler
│   │   │   ├── CallRecorder.php
│   │   │   ├── Composite.php
│   │   │   ├── FrozenObjectCheck.php
│   │   │   ├── IInvocationHandler.php
│   │   │   ├── MagicCallRecorder.php
│   │   │   └── StubCaller.php
│   │   └── MockClass.php
│   ├── Client
│   │   ├── Default.php
│   │   ├── IClient.php
│   │   └── PHPUnit.php
│   ├── Exception
│   │   ├── MethodMatcherException.php
│   │   └── VerificationException.php
│   ├── Facade.php
│   ├── IMock.php
│   ├── Matchers
│   │   ├── AbstractChainableArgumentMatcher.php
│   │   ├── AnyParameters.php
│   │   ├── ArgumentCaptor.php
│   │   ├── ChainedArgumentMatcher.php
│   │   ├── EqualsMatcher.php
│   │   ├── Factory.php
│   │   ├── HamcrestMatcherAdapter.php
│   │   ├── IArgumentMatcher.php
│   │   ├── IChainableArgumentMatcher.php
│   │   ├── IMethodMatcher.php
│   │   ├── IgnoreRemainingMatcher.php
│   │   ├── MethodMatcher.php
│   │   ├── PHPUnitConstraintAdapter.php
│   │   ├── ReferenceSetter.php
│   │   └── SingleArgumentMatcher.php
│   ├── Mock
│   │   ├── Freezer.php
│   │   ├── Info.php
│   │   └── InfoRegistry.php
│   ├── PHPUnit
│   │   ├── VerifierResultConstraint.php
│   │   └── VerifierResultConstraintV3d6.php
│   ├── Proxies
│   │   ├── AnswerBinderProxy.php
│   │   ├── AnswerCollectionProxy.php
│   │   ├── CallStubberProxy.php
│   │   ├── CallVerifierProxy.php
│   │   ├── StaticVisibilityProxy.php
│   │   ├── StubberProxy.php
│   │   ├── VerifierProxy.php
│   │   └── VisibilityProxy.php
│   ├── String
│   │   └── Converter.php
│   └── Stubber
│       ├── AnswerBinder.php
│       ├── AnswerCollection.php
│       ├── Answers
│       │   ├── ExceptionAnswer.php
│       │   ├── InvalidAnswerException.php
│       │   ├── LambdaAnswer.php
│       │   ├── NoAnswer.php
│       │   ├── ParentDelegate.php
│       │   ├── ParentDelegateCallback.php
│       │   ├── SelfAnswer.php
│       │   ├── SmartDefaultAnswer.php
│       │   └── StaticAnswer.php
│       ├── IAnswer.php
│       ├── IAnswerBinder.php
│       ├── IAnswerContainer.php
│       ├── SelfBindingAnswerBinder.php
│       └── StubMapper.php
└── Phake.php

PhakeはPhake.phpがファサードになっていてstaticに呼び出すのが特徴です。

Phakeの使い方

Phakeの使い方を前回同様以下の例を使って確認します。

例の補足

モック化の確認をしやすいように以下のパターンを用意しています。

  • 自分の中だけで完結する処理をするメソッド
  • クラス内のgetterを呼び出して処理しているメソッド
  • クラス内のsetterを呼び出して処理しているメソッド
  • privateメソッド
  • staticメソッド
class Example {
    private $total = 0;
    private static $static_total = 1;
    public function __construct() {
        $this->total = 1;
        self::$static_total = 2;
    }
    public function plusA() {
        return $this->total += 1;
    }
    public function plusB() {
        $this->total = $this->getTotal();
        return $this->total += 1;
    }
    public function plusC() {
        $this->setTotal(10);
        return $this->total += 1;
    }
    private function plusD() {
        return $this->total += 1;
    }
    public function getTotal() {
        return $this->total;
    }
    public function setTotal($total) {
        $this->total = $total;
    }
    public static function getStaticTotal() {
        return self::$static_total;
    }
}

Phake::mockで全モック

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

/**
 * 全部握りつぶし
 *
 * 引数:クラスのみ
 * コンストラクタ:呼ばれない
 */
public function test_mock() {
    $example = Phake::mock(Example::class);
    $result = $example->plusA();
    $this->assertNull($result);
    $result = $example->plusB();
    $this->assertNull($result);
    $result = $example->plusC();
    $this->assertNull($result);
}
イメージ

%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

Phake::mockで振る舞い設定

コンストラクタは呼ばれず全てのメソッドは握りつぶし、plusAにだけ返り値を設定します。

/**
 * 全部握りつぶし
 * plusAだけ振る舞い設定
 *
 * 引数:クラスのみ
 * コンストラクタ:呼ばれない
 */
public function test_mock_setting() {
    $example = Phake::mock(Example::class);
    Phake::when($example)->plusA()->thenReturn('A');
    $result = $example->plusA();
    $this->assertEquals('A', $result);
}
イメージ

%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

Phake::partialMockで部分モック

partialMockだけを使った場合

まずpartialMockだけを使った場合、全ての振る舞いは元のままとなります。後述しますがこの場合verifyが使えます。

/**
 * 全部そのまま
 *
 * 引数:クラス(コンストラクタに値を渡す場合は引数追加)
 * コンストラクタ:呼ばれる
 */
public function test_partialMock_non() {
    $example = Phake::partialMock(Example::class);
    $result = $example->plusA();
    $this->assertEquals(2, $result);
    $result = $example->plusB();
    $this->assertEquals(3, $result);
    $result = $example->plusC();
    $this->assertEquals(11, $result);
}
イメージ

%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-20-19-38-07

partialMockで振る舞いを設定する場合

partialMockを使った後に以下のように振る舞いを設定します。PHPUnitのモックオブジェクトのcreateMockメソッドとは違いコンストラクタは呼ばれます。

/**
 * 全部そのまま
 * 指定したメソッドのみ振る舞い設定
 *
 * 引数:クラス(コンストラクタに値を渡す場合は引数追加)
 * コンストラクタ:呼ばれる
 */
public function test_partialMock_partial() {
    $example = Phake::partialMock(Example::class);
    Phake::when($example)->getTotal()->thenReturn(3);
    $result = $example->plusA();
    $this->assertEquals(2, $result);
    $result = $example->plusB();
    $this->assertEquals(4, $result);
    $result = $example->plusC();
    $this->assertEquals(11, $result);
}
イメージ

%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-20-19-45-49

どのように呼ばれたかを確認する

Phakeの場合どのように呼ばれたかのチェックは通常処理実行後にverifyを使って行います。getterやsetterがどの引数で何回呼ばれたかを確認するには以下のように書きます。

/**
 * 全部そのまま
 * 期待動作確認(1 test, 5 assertions)
 *
 * 引数:クラス(コンストラクタに値を渡す場合は引数追加)
 * コンストラクタ:呼ばれる
 */
public function test_partialMock_setStubMethod() {
    $example = Phake::partialMock(Example::class);
    $result = $example->plusA();
    $this->assertEquals(2, $result);
    $result = $example->plusB();
    $this->assertEquals(3, $result);
    $result = $example->plusC();
    $this->assertEquals(11, $result);
    Phake::verify($example, Phake::times(1))->getTotal();
    Phake::verify($example, Phake::times(1))->setTotal(10);
}

privateメソッドをモック化する

ここまではPHPUnitのモックオブジェクトとそれほど変わりませんが、Phakeを使えばprivateメソッドを簡単に実行したりモック化することができます。

Phake::makeVisibleを使って普通に実行する

Phake::makeVisibleを使うことでprivateメソッドを実行することができます。

/**
 * 全部握りつぶさない
 * privateメソッドを普通に実行
 *
 * 引数:クラスのみ
 * コンストラクタ:呼ばれる
 */
public function test_partialMock_private() {
    $example = Phake::partialMock(Example::class);
    // 直接は呼び出せないのでmakeVisibleにてプロキシして実行確認可能
    $result = Phake::makeVisible($example)->plusD();
    $this->assertEquals(2, $result);
}

モック化する

以下のように普通にprivateなスタブメソッドに振る舞いを設定することもできます。

/**
 * 全部握りつぶさない
 * privateメソッドの振る舞いを設定
 *
 * 引数:クラスのみ
 * コンストラクタ:呼ばれる
 */
public function test_partialMock_private2() {
    $example = Phake::partialMock(Example::class);
    // 普通に振る舞い設定
    Phake::when($example)->plusD()->thenReturn(5);
    // 直接は呼び出せないのでmakeVisibleにてプロキシして実行確認可能
    $result = Phake::makeVisible($example)->plusD();
    $this->assertEquals(5, $result);
}

whenStaticを使ってstaticメソッドをモック化する

PhakeならstaticメソッドもPhake::whenStaticを使って簡単にモック化できてしまいます。

/**
 * 全部握りつぶし
 * staticメソッドの振る舞いを設定
 *
 * 引数:クラスのみ
 * コンストラクタ:呼ばれない
 */
public function test_partialMock_static() {
    // そのまま実行する場合
    $result = Example::getStaticTotal();
    $this->assertEquals(1, $result);
    $example = Phake::partialMock(Example::class);
    // 直接はNG
    $result = $example::getStaticTotal();
    $this->assertNull($result);
    // 振る舞い設定
    Phake::whenStatic($example)->getStaticTotal()->thenReturn(3);
    $result = $example::getStaticTotal();
    $this->assertEquals(3, $result);
}

その他に便利なもの

thenCallParent

以下のようにPhake::mockで全部握りつぶしたとしてもthenCallParentを使えば元の処理を呼び出すことができます。

/**
 * 全部握りつぶし
 * privateメソッドをスタブ化する
 *
 * 引数:クラスのみ
 * コンストラクタ:呼ばれない
 */
public function test_mock_private2() {
    $example = Phake::mock(Example::class);
    Phake::when($example)->plusD()->thenCallParent();
    // 普通にスタブ化
    Phake::when($example)->plusD()->thenReturn(5);
    // 直接は呼び出せないのでmakeVisibleにてプロキシして実行確認可能
    $result = Phake::makeVisible($example)->plusD();
    $this->assertEquals(5, $result);
}

一括で振る舞いを設定する

モックに個別に振る舞いを設定するのが面倒なときは、Phake::ifUnstubbedを使って一括で設定できてしまいます。

/**
 * 全部スタブ化
 * 振る舞いを一括設定
 *
 * 引数:クラスのみ
 * コンストラクタ:呼ばれない
 */
public function test_mock_setting2() {
    $example = Phake::mock(Example::class, Phake::ifUnstubbed()->thenReturn('A'));
    $result = $example->plusA();
    $this->assertEquals('A', $result);
    $result = $example->plusB();
    $this->assertEquals('A', $result);
    $result = $example->plusC();
    $this->assertEquals('A', $result);
    $result = Phake::makeVisible($example)->plusD();
    $this->assertEquals('A', $result);
}

カバレッジレポート

最後にカバレッジレポートを見てみます。ソースはこちらにあります。
%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-20-20-35-31
%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-20-20-35-05
きました、オールグリーン!もちろんモック確認の為のクラスなんでオールグリーンになったところでたいした意味はありませんが、Phakeを使えば簡単にprivateもstaticもモック化できてとにかく楽ちんです。

まとめ

ここまで簡単にモック化できてしまうとPHPのモッキンフレームワークはPhakeで十分ですね。また、期待動作の設定を処理実行後のverifyで行うのも直感的でわかりやすいです。

今回使ったPHPUnitとPhakeのバージョン
  • “phpunit/phpunit”: “5.6.*”,
  • “phake/phake”: “2.3.*”,
Posted on

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

前回は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モックオブジェクトのファイル構成は以下の通りです。

├── Builder
│   ├── Identity.php
│   ├── InvocationMocker.php
│   ├── Match.php
│   ├── MethodNameMatch.php
│   ├── Namespace.php
│   ├── ParametersMatch.php
│   └── Stub.php
├── Exception
│   ├── BadMethodCallException.php
│   ├── Exception.php
│   └── RuntimeException.php
├── Generator
│   ├── deprecation.tpl.dist
│   ├── 省略...
├── Generator.php
├── Invocation
│   ├── Object.php
│   └── Static.php
├── Invocation.php
├── InvocationMocker.php
├── Invokable.php
├── Matcher
│   ├── AnyInvokedCount.php
│   ├── AnyParameters.php
│   ├── ConsecutiveParameters.php
│   ├── Invocation.php
│   ├── InvokedAtIndex.php
│   ├── InvokedAtLeastCount.php
│   ├── InvokedAtLeastOnce.php
│   ├── InvokedAtMostCount.php
│   ├── InvokedCount.php
│   ├── InvokedRecorder.php
│   ├── MethodName.php
│   ├── Parameters.php
│   └── StatelessInvocation.php
├── Matcher.php
├── MockBuilder.php
├── MockObject.php
├── Stub
│   ├── ConsecutiveCalls.php
│   ├── Exception.php
│   ├── MatcherCollection.php
│   ├── Return.php
│   ├── ReturnArgument.php
│   ├── ReturnCallback.php
│   ├── ReturnReference.php
│   ├── ReturnSelf.php
│   └── ReturnValueMap.php
├── Stub.php
└── Verifiable.php

今回は中でも主要処理のある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を使う場合コンストラクタ含め例外を除く全メソッドが握りつぶされます。
protected function createMock($originalClassName)
{
    return $this->getMockBuilder($originalClassName)
                ->disableOriginalConstructor()
                ->disableOriginalClone()
                ->disableArgumentCloning()
                ->disallowMockingUnknownTypes()
                ->getMock();
}

createPartialMock

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

protected function createPartialMock($originalClassName, array $methods)
{
    return $this->getMockBuilder($originalClassName)
                ->disableOriginalConstructor()
                ->disableOriginalClone()
                ->disableArgumentCloning()
                ->disallowMockingUnknownTypes()
                ->setMethods(empty($methods) ? null : $methods)
                ->getMock();
}

createConfiguredMock

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

protected function createConfiguredMock($originalClassName, array $configuration)
{
    $o = $this->createMock($originalClassName);
    foreach ($configuration as $method => $return) {
        $o->method($method)->willReturn($return);
    }
    return $o;
}

モック生成の具体例

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

テスト対象のクラス例

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

  • ただ処理するだけのメソッド
  • クラス内のgetterを呼び出して処理しているメソッド
  • クラス内のsetterを呼び出して処理しているメソッド
  • privateメソッド
  • staticメソッド
class Example {
    private $total = 0;
    private static $static_total = 1;
    public function __construct() {
        $this->total = 1;
        self::$static_total = 2;
    }
    public function plusA() {
        return $this->total += 1;
    }
    public function plusB() {
        $this->total = $this->getTotal();
        return $this->total += 1;
    }
    public function plusC() {
        $this->setTotal(10);
        return $this->total += 1;
    }
    private function plusD() {
        return $this->total += 1;
    }
    public function getTotal() {
        return $this->total;
    }
    public function setTotal($total) {
        $this->total = $total;
    }
    public static function getStaticTotal() {
        return self::$static_total;
    }
}

createMockで全モック

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

/**
 * 全メソッド握りつぶす
 *
 * 引数:クラスのみ
 * コンストラクタ:呼ばれない
 */
public function test_createMock_all() {
    $this->example = $this->createMock(Example::class);
    $result = $this->example->plusA();
    $this->assertNull($result);
    $result = $this->example->plusB();
    $this->assertNull($result);
    $result = $this->example->plusC();
    $this->assertNull($result);
}

イメージ
全部呼び出せない。
%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だけに振る舞い設定
 *
 * 引数:クラスのみ
 * コンストラクタ:呼ばれない
 */
public function test_createMock_all_stub() {
    $this->example = $this->createMock(Example::class);
    $this->example->expects($this->once())->method('plusA')->willReturn('A');
    $result = $this->example->plusA();
    $this->assertEquals('A', $result);
}

イメージ
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で部分モック

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

/**
 * 一部握りつぶす
 *
 * 引数:クラスとメソッド
 * コンストラクタ:呼ばれない
 */
public function test_createPartialMock_partial() {
    $this->example = $this->createPartialMock(Example::class, ['getTotal']);
    $result = $this->example->plusA();
    $this->assertEquals(1, $result);
    // getTotalは振る舞いを設定していないためnullとなるがエラーにはならない
    $result = $this->example->plusB();
    $this->assertEquals(1, $result);
    $result = $this->example->plusC();
    $this->assertEquals(11, $result);
}

イメージ
一部握りつぶし他は元のまま
%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
振る舞いを指定する場合は以下のようにする

/**
 * 一部スタブ化&振る舞い設定
 *
 * 引数:クラスとメソッド
 * コンストラクタ:呼ばれない
 */
public function test_createPartialMock_setStub() {
    $this->example = $this->createPartialMock(Example::class, ['getTotal']);
    $this->example->expects($this->once())->method('getTotal')->willReturn(3);
    $result = $this->example->plusA();
    $this->assertEquals(1, $result);
    $result = $this->example->plusB();
    $this->assertEquals(4, $result);
    $result = $this->example->plusC();
    $this->assertEquals(11, $result);
}

イメージ
一部握りつぶし振る舞いを設定し他は元のまま
%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のようにどの引数で何回呼ばれたかを確認するには以下のように書きます。

/**
 * 一部スタブ化&期待値設定(1 test, 4 assertions)
 *
 * 引数:クラスとメソッド
 * コンストラクタ:呼ばれない
 */
public function test_createPartialMock_setStub2() {
    $this->example = $this->createPartialMock(Example::class, ['setTotal']);
    $this->example->expects($this->once())->method('setTotal')->with(10);
    $result = $this->example->plusA();
    $this->assertEquals(1, $result);
    $result = $this->example->plusA();
    $this->assertEquals(2, $result);
    // setTotalは期待値の設定はあるが振る舞いはないので実行はされない
    $result = $this->example->plusC();
    $this->assertEquals(3, $result);
}

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

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

method

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

willReturn

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

expects

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

with

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

カバレッジレポート

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

phpunit --bootstrap Bootstrap.php --coverage-html ./report --whitelist src/ test/ExamplePhpUnitMockTest.php

カバレッジレポート
%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.*”