はじめに
Laravel Dusk を使っていると、こんな現象に遭遇することがあります。
php artisan migrate --env=dusk
php artisan dusk
にも関わらず、
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'posts' doesn't exist
「いや、migrate してるやん…?」
「paginate で 0 件取得するだけなのに…?」
「テーブルできてないの…?」
ってなった際の対処法を解説していきます。
▪️なぜこの現象が起きるのか
▪️なぜ use DatabaseMigrations; を付けると解決するのか
▪️「DBが違うから」では説明できない理由
→そもそも「migrate」ではなく、「use DatabaseMigrations;」すべき
って話です。
結論
ここがポイント
原因は DB ではなく、Laravel の「⭐️インスタンス⭐️」が違うこと。
▪️手動migrate:CLI で起動した Laravel
▪️Duskテスト:Dusk が起動した Laravel(別インスタンス)
DatabaseMigrationsは
「Dusk が実際に使う Laravel インスタンス自身に migrate させる仕組み」。
勘違いポイント
「migrate してるんだから table はあるはず」
これは 同一インスタンス前提なら正しい。
しかし Dusk では前提が崩れます。
Laravel Dusk の実際の構造
手動 migrate のとき
php artisan migrate --env=dusk
▪️CLI から Laravel を起動
▪️Laravel インスタンス A
▪️DB に migrate を実行
Laravel A ── migrate ──> DB
Dusk 実行時
php artisan dusk
▪️PHPUnit が起動
▪️Dusk が Laravel を再度ブート
▪️Laravel インスタンス B
▪️ブラウザは B を叩く
Laravel B ── index() ──> paginate() ──> DB
👉 A と B は別インスタンス
重要なポイント
▪️DB は共有されている
▪️しかし Laravel の初期化状態は共有されない
つまり、
▪️migrate は A の仕事
▪️テストは B の世界
▪️B は
→migrate を実行していない
→DB の正当性を一切保証していない
なぜ DatabaseMigrations を付けると直るのか
use Illuminate\Foundation\Testing\DatabaseMigrations;
class PostIndexTest extends DuskTestCase
{
use DatabaseMigrations;
}
これがやっていること:
Dusk が起動した Laravel(B)
└─ テスト開始前に migrate:fresh を実行
└─ その DB を使ってテスト
👉 migrate と paginate が完全に同じ世界