MockeryのshouldReceiveはonceをつけないと意味がない


はじめに

  • Mockeryでハマったので他の人がハマらないようにメモ書きを残す

通常サンプル

MyClass.php
class MyClass {
    public function get_message($name) {
        return $this->get_hello() . $name;
    }

    public function get_hello() {
        return 'Hello ';
    }
}
MyClassTest.php
class MyClassTest {
    public function test_get_message(){
        $object = new MyClass();
        $result = $object->get_message('TEST');
        $expect = 'Hello TEST';
        $this->assertSame($expect, $result);
    }
}

普通に使う場合はこんな感じで書けるかと思います

該当のソース

MyClassTest.php
class MyClassTest {
    public function test_get_message(){
        $testDouble = \Mockery::mock(MyClass::class)->makePartial();
        $testDouble->shouldReceive('dummy_method');

        $result = $testDouble->get_message('TEST');
        $expect = 'Hello TEST';
        $this->assertSame($expect, $result);
    }
}

dummy_methodという存在しないメソッドがshouldReceive(呼び出されていること)をテストしています。
dummy_methodは存在しないし呼び出してもいないので当然テストは失敗する、と思いたかったんですが実はこのテスト成功してしまいます。

対策

以下のように書けばうまくいきます

MyClassTest.php
class MyClassTest {
    public function test_get_message(){
        $testDouble = \Mockery::mock(MyClass::class)->makePartial();
        $testDouble->shouldReceive('dummy_method')->once();

        $result = $testDouble->get_message('TEST');
        $expect = 'Hello TEST';
        $this->assertSame($expect, $result);
    }
}
E                                                                   1 / 1 (100%)

Time: 12.39 seconds, Memory: 26.00MB

There was 1 error:

1) XXX::test_get_message
Mockery\Exception\InvalidCountException: Method dummy_method(<Any Arguments>) from Mockery_0_XXX should be called
 exactly 1 times but called 0 times.

1回呼び出されることを想定していて0回呼び出しだったので正しく失敗してくれています

まとめ

この動きが正しいのかよく分かりません
もしかしたら使い方が間違っているだけなのかもしれないので有識者の方コメントをお願いします
ひとまずは「呼び出されたこと」をテストしたい場合は必ずonceなどの回数指定のものを設定しましょう