[PHPUnit]あるクラスの指定のメソッドのみをmockするやり方


概要

PHPUnitのテストをやっているとやっぱりmockを使えると便利ですよね!
ということでmockを使ったテストのやり方についてです

さっそくやってみる

まずこんな感じのテストしたいクラスがあることにしましょう。

target.php
class Target{

    private $otherClass;

    public function construct(OtherClass $otherClass)
    {
        $this->otherClass = $otherClass;
    }

    public function start()
    {
        //ここで色々な処理があるとする
        try{
            $result = $this->next();
            return $result;
        }catch(Exception $e){
            return false;
        }
    }

    public function next()
    {
        //なんらかの処理をしてその結果を返す
        $processResult = $this->process();
        if($processResult === true){
            return true;
        }else{
            return false;
        }
    }
}

コンストラクタのインジェクションで別のクラスが注入されてて、start関数がnext関数を呼んでいるとしましょう。
start関数は色々な処理をした後にnext関数を呼んでいて、next関数はなんらかの処理をしたあとその結果を返します。

このときに、next関数だけをmockにしてstart関数はそのままの状態でテストしたかったのでこう書きました!

test.php
class Test{

    public function test001()
    {
        //makePartialを使うことでshouldReceiveを設定したクラスのみをモックにすることが可能。mockの第二引数はコンストラクタ
        $targetClassMock = Mockery::mock(Target::class, [OtherClass::class])->makePartial();
        //next関数が呼ばれたらtrueを返すようにモックを設定する
        $targetClassMock->shouldReceive('next')->andReturn(false);
        //start関数をコール
        $ret = $targetClassMock->start();
        //Trueであることを確認
        $this->assertTrue($ret);
    }
}

また、next関数で例外が発生したときに、それがちゃんとキャッチされてreturn falseを返せるかも確認したいです。
そういうときはこう書きます。

test.php
class Test{

    public function test002()
    {
        //さっきと同じ
        $targetClassMock = Mockery::mock(Target::class, [OtherClass::class])->makePartial();
        //next関数が呼ばれたらエラーが発生するようにモックを設定する
        $targetClassMock->shouldReceive('next')->andThrow(new Exception('test002だよ');
        //さっきと同じ
        $ret = $targetClassMock->start();
        //falseであることを確認
        $this->assertFalse($ret);
    }
}

まだまだ他にも奥が深そうですが、自分がやりたいことは一旦できたので共有ここまで。
もっと色々と手を出してみたいですね!