もがき系プログラマの日常

もがき系エンジニアの勉強したこと、日常のこと、気になっている技術、備忘録などを紹介するブログです。

DBが複数存在する場合のRefreshDatabaseトレイトを使ったテスト

はじめに

こんばんは。

Laravelでテスト書く際に 最初に必要なSeederを読み込んで 各テストを行いたい場合ってよくあると思いますが、その際は必ず RefreshDatabase トレイトをuseする必要があります。

そのさいDBが複数存在する場合に限りうまくいきません。

色々調べたのですが以下の例のように RefreshDatabase の処理をオーバライドする必要がありそうです。

qiita.com

本題

<?php

namespace Tests;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\RefreshDatabaseState;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;

abstract class TestCase extends BaseTestCase
{
    use CreatesApplication;
    use RefreshDatabase;

    protected string $seeder = TestCaseSeeder::class;

    protected array $connectionsToTransact = ['mysql', 'mysql2', 'mysql3'];

    ↓以下をオーバライド
    protected function refreshTestDatabase()
    {
        if (! RefreshDatabaseState::$migrated) {
            foreach ($this->connectionsToTransact() as $database) {
                $this->artisan('db:wipe', array_filter([
                    '--database' => $database,
                    '--drop-views' => $this->shouldDropViews(),
                    '--drop-types' => $this->shouldDropTypes(),
                    '--force' => true,
                ]));
            }

            $this->artisan('migrate', [
                '--seeder' => $this->seeder,
                '--force'  => true,
            ]);

            $this->app[Kernel::class]->setArtisan(null);

            RefreshDatabaseState::$migrated = true;
        }

        $this->beginDatabaseTransaction();
    }
}

db:wipeはDB数分実行が必要で、migrateに関してはmigrationsテーブルを作成するためにデフォルトの指定のみでOK。

終わりに

なんかもっと良さげな解決法ありそうですがね。。。。

なにか知ってたら誰か教えてください。