読者です 読者をやめる 読者になる 読者になる

PHPUnitのMockが生成するコード

PHPUnitのMockはコードを生成してeval()しているわけだけれども、PHPUnit_Framework_TestCase#getMockBuilder()の引数に存在しないクラス名を渡すと、そのクラスを生成するコードも出力する。

どんなコードを生成しているかはこのように確認できる。

<?php
require_once('Text/Template.php');
require_once('PHPUnit/Framework/MockObject/Generator.php');
$mock = PHPUnit_Framework_MockObject_Generator::generate('Foo');
echo $mock['code'];

実行結果:

class Foo
{
}

class Mock_Foo_ce23079e extends Foo implements PHPUnit_Framework_MockObject_MockObject
{
    protected static $staticInvocationMocker;
    protected $invocationMocker;

    public function __clone()
    {
        $this->invocationMocker = clone $this->__phpunit_getInvocationMocker();
    }

    public function expects(PHPUnit_Framework_MockObject_Matcher_Invocation $matcher)
    {
        return $this->__phpunit_getInvocationMocker()->expects($matcher);
    }
...

と、Fooを作ってからそのサブクラスを作って、そのオブジェクトをMockとして返している。

何でこんなことを調べたのかというと、Fooが存在しているつもりでモックを作ったのだが実は存在していなかった(requireされていなかった)、で、本当はFooのコンストラクタには引数が必要だったのだがそれを忘れていた。だがここでのFooはMockObject_Generatorが作った空のFooなので当然エラーにはならない。単体では。
しかしこれを他のテストケースと一緒に実行すると、別のところでFooがrequireされていたためにエラーが発覚する。というはまり方をしたためです。