0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

なんかいい感じに解決してくれる!Laravelのサービスコンテナ先生

Last updated at Posted at 2025-09-12

【今回のお話の環境】
Laravel:12.19.3
pest:3.8.2
mockery:1.6.12

開発中、HogeUseCaseをテストしたいけど、UseCaseの中でnewしているFugaServiceをモックしないとうまくテストが通らない...という壁にぶち当たりました。この問題の解決までの道のりと最終的な解決方法を備忘録的に残します!

【解決までの道のり】

  1. chatGPT「overloadをしてみればいいんじゃね?」

    • RuntimeException Could not load mock FugaService, class already existsというエラーが出てテストが失敗する
  2. 似たような苦しみをしてる人いないかな...

    • 同じような苦しみをしているstackoverflowの投稿
      • その投稿内でこんなコメントが↓
        if it is using the new keyword, it is extremely complex to get over it, I would say impossible... can't you change that code to resolve(Connector::class);
        (訳:newしちゃうとメチャメチャ話が難しくなっちゃうよ。resolve(Connector::class)を試してみて。)
  3. resolve(Connector::class)を調べてみる
    - "サービスコンテナ"に出会う

サービスコンテナ

Q:「いい感じ」とは?

A:インスタンスの中で使うインスタンス(今回の例ではHogeUseCaseの中で使っているFugaService)をサービスコンテナ側で用意してくれるので、インスタンスの中身を気にしなくて済む(詳しくは参考記事へ...)

今回の使い方

今回やりたかったのは"HogeUseCaseのテストを中で呼ばれるFugaServiceを意識せずに行う"事でした。
そこで、今回は

  1. HogeUseCase内でFugaServiceをnewするのではなくapp()->make()で依存解決する
  2. HogeUseCaseTestにてFugaServiceをモックする
  3. HogeUseCaseを宣言する前にapp()->instance()で依存解決の時にモックしたインスタンスを使うようにする
  4. あとは普通にHogeUseCaseを宣言!

コード例

実装側

class HogeUseCase
{
    public function __invoke()
    {
        // 前略
        $fugaService = app()->make(FugaService::class);
        // 後略
    }
}

テスト側

$mock = Mockery::mock(FugaService::class);
$mock->shouldReceive('HogeUseCase内で使ってるインスタンスメソッド')
    ->andReturn(想定される返し値);

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

$usecase = new HogeUseCase;

インスタンスの中で別インスタンスを使う場面はこれから先も多く、それらをテストする場面もそれに応じて増えていくと思われます。そんな時にサービスコンテナのことを思い出したいですね。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?