Laravel Mockery: method does not exist on this mock object
Laravel + Mockeryでメソッドが存在しないエラーが発生する場合の原因と解決策。actingAsとMockの順序問題
概要
Laravel + Mockeryでテストを書く際、Mockが正しく設定されているはずなのに「method does not exist on this mock object」エラーが発生する問題。特に $this->actingAs() との組み合わせで起きやすい、見つけにくいバグです。
エラーメッセージ
Mockery\Exception\BadMethodCallException: Method Mockery_0_App_Services_SomeService::someMethod() does not exist on this mock object
原因
- actingAsとMockの順序問題:
actingAs()の後にMockをバインドしている - サービスコンテナの解決タイミング: 認証時に依存関係が先に解決される
- Mockのバインドが遅い: 既に解決済みのインスタンスは置き換わらない
なぜ見つけにくいのか
- 他のテストからコードをコピーしても動かない
- エラーメッセージからは順序問題と分からない
actingAs()の位置を意識することが少ない- 公式ドキュメントに明記されていない
解決策
1. Mockを actingAs より先にバインドする
| |
| |
2. setUp() でMockをバインドする
| |
3. partialMock を使う(Laravel 8+)
| |
4. mock() ヘルパーを使う
| |
原因の詳細
サービスコンテナの解決タイミング
1. actingAs($user) を呼ぶ
2. 認証ガードが初期化される
3. ガードの依存関係がサービスコンテナから解決される
4. この時点で SomeService の実インスタンスが生成・キャッシュされる
5. 後から Mock をバインドしても、既に解決済みのインスタンスは使われ続ける
なぜ他のテストからコピーしても動かないのか
| |
デバッグ方法
| |
よくある間違い
actingAs()の後に Mock をバインドするshouldReceive()でメソッド名をタイポ- 部分モックなのに
makePartial()を忘れる - singleton でバインドされているサービスを instance でバインドしようとする
関連エラー
関連エラー
PHP の他のエラー
この記事は役に立ちましたか?