LoginSignup
2
0

More than 5 years have passed since last update.

LumenのDatabaseMigrationsトレイトの初期化問題に対処する

Posted at

はじめに

LumenでDBを使用したテストを行う際にDBの初期化を行うために Laravel\Lumen\Testing\DatabaseMigrations というトレイトが提供されています。これは基本的には開始時にmigrateを行い終了時にmigrate:rollbackすることできれいにする、という動作をしますが、テストが異常終了するときちんとrollbackできずDBに中身が残ることがあって、その状態になると次回のテストが中身が残った状態で開始されてしてしまいテスト内容によっては失敗してしまいます。

これはDatabaseMigrations trait doesn't revert DB inserts and deletes #775で報告されている問題です。本家のLaravelでは開始時にmigrateではなくmigrate:freshを行うようになっていてこの問題は解決済みですが、Lumenには取り込まれていません。

Laravelの修正を取り込む

Lumenはそのうち直るとしてもいつになるかわからないので、今できる対処としてLaravel\Lumen\Testing\DatabaseMigrationsが開始時に実行するmigrateコマンドをmigrate:refresh1にしたMyDatabaseMigrationsトレイトを作ってそれを使うようにしようというのはすぐ思いつきます。

そこで最初以下のようなものを作ってみたのですがうまくいきませんでした。migrationが全く行われません。

trait MyDatabaseMigrations
{

    public function runDatabaseMigrations()
    {
        $this->artisan('migrate:refresh');

        $this->beforeApplicationDestroyed(function () {
            $this->artisan('migrate:rollback');
        });
    }
}

呼び出し元を調べたところ、runDatabaseMigrationsを呼ぶかどうかはLaravel\Lumen\Testing\DatabaseMigrationsトレイトをuseしているかどうかで判定していました。(Laravel\Lumen\Testing\TestCaseクラスのsetUpTraitsメソッド)

    protected function setUpTraits()
    {
        $uses = array_flip(class_uses_recursive(get_class($this)));

        if (isset($uses[DatabaseMigrations::class])) {
            $this->runDatabaseMigrations();
        }

        ...
    }

従って正解はさらにLaravel\Lumen\Testing\DatabaseMigrationsをuseするようにして以下のようになります。

trait MyDatabaseMigrations
{
    use \Laravel\Lumen\Testing\DatabaseMigrations;

    public function runDatabaseMigrations()
    {
        $this->artisan('migrate:refresh');

        $this->beforeApplicationDestroyed(function () {
            $this->artisan('migrate:rollback');
        });
    }
}

runDatabaseMigrationsしかないトレイトをuseしてその唯一のメソッドがいきなり上書きされてしまうわけですが、そのトレイトをuseしたという事実が重要です。

さらによくよく見ると、beforeApplicationDestroyedで行っているロールバックも開始時にmigrate:refreshを行うという前提なら無駄な気がします。むしろテスト後にDBの中身をちょっと見られて便利でもあるので自分は削ってしまいました。

最終的には以下のようなものを使用しています。

trait MyDatabaseMigrations
{
    use \Laravel\Lumen\Testing\DatabaseMigrations;

    public function runDatabaseMigrations()
    {
        $this->artisan('migrate:refresh');
    }
}

  1. migrate:freshではなくmigrate:refreshになっているのは、Lumenにはいまのところmigrate:freshコマンドがないからです 

2
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
2
0