エンジニアのひよこ_level10

毎日更新してた人。たまに記事書きます。

【Mockery】テスト対象のメソッド内で、app関数で値が呼び出されているとき【403日目】

こんなとき

class Hoge
{
    public function fuga()
    {
        return app('some_class')->someMethod();
    }
}
class SomeClassProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->singleton('some_class', function () {
            return new SomeClass();
        });
    }
}

appでインスタンス呼ばれてるうううう

テスト書くときどうしよう?

使うもの

$this->app->instance(Hoge::class, $mock);

テストコード

public function testFuga()
{
    $mock = Mockery::mock('SomeClass');
    $mock->shouldReceive('someMethod')
        ->once()
        ->andReturn('hoge');

    $this->app->instance('some_class',$mock);

    $this->assertSame($this->hoge->fuga(), 'hoge');
}

何をしているのか

appの結合を新しく宣言しました。

通常時は、SomeClassProviderで'some_class'に対してsingleton結合されていました。
使われるクラスは、 singletonで作られた、SomeClassのインスタンスです。

これに対してテストコード内では、'some_class'に対して、$mockのインスタンスを返す、instance結合を宣言しました。
なので、テスト実行時にapp('some_class')をすると、$mockのインスタンスが返されます。

これによって、$mockによる関数実行が行えます!

参考

サービスコンテナ 5.3 Laravel

appではなく、newされてる場合

www.nyamucoro.com