web-dev-qa-db-ja.com

laravelテストのデータベース移行をシードする方法は?

Laravelの ドキュメント は、テスト間でデータベースを移行およびロールバックするためにDatabaseMigrations特性を使用することを推奨しています。

use Illuminate\Foundation\Testing\DatabaseMigrations;

class ExampleTest extends TestCase
{
    use DatabaseMigrations;

    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        $response = $this->get('/');

        // ...
    }
}

ただし、テストで使用するシードデータがいくつかあります。私が実行した場合:

php artisan migrate --seed

その後、最初のテストでは機能しますが、後続のテストでは失敗します。これは、特性が移行をロールバックし、移行を再度実行するときにデータベースをシードしないためです。移行時にデータベースシードを実行するにはどうすればよいですか?

15
Jeff Puckett

あなたがする必要があるのは、職人の電話をかけることですdb:seed setUp関数内

<?php

use Illuminate\Foundation\Testing\DatabaseMigrations;

class ExampleTest extends TestCase
{
    use DatabaseMigrations;

    public function setUp(): void
    {
        parent::setUp();

        // you can call
        $this->artisan('db:seed');

        // or 
        $this->seed();
    }

    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        $response = $this->get('/');

        // ...
    }
}

参照: https://laravel.com/docs/5.6/testing#creating-and-running-tests

17
lasec0203

これを理解するには掘り下げたので、 共有したいと思った

DatabaseMigrations trait のソースコードを見ると、1つの関数 runDatabaseMigrations が呼び出されていることがわかります。 setUp which すべてのテストの前に実行 そして、分解時に実行されるコールバックを登録します。

"extend" trait the trait を並べ替えることができます。そのためには、その関数のエイリアスを作成し、ロジックを含む新しい関数を再宣言します(artisan db:seed)元の名前で、その中のエイリアスを呼び出します。

use Illuminate\Foundation\Testing\DatabaseMigrations;

class ExampleTest extends TestCase
{
    use DatabaseMigrations {
        runDatabaseMigrations as baseRunDatabaseMigrations;
    }

    /**
     * Define hooks to migrate the database before and after each test.
     *
     * @return void
     */
    public function runDatabaseMigrations()
    {
        $this->baseRunDatabaseMigrations();
        $this->artisan('db:seed');
    }

    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        $response = $this->get('/');

        // ...
    }
}
20
Jeff Puckett

この質問にはすでに何度か答えられていることは知っていますが、この特定の答えが見当たらないので、私はそれを投げ入れると思いました。

laravel(少なくともv5.5以降))ではしばらくの間、TestCaseクラスにデータベースシーダーの呼び出しに特に使用されるメソッドがありました。

https://laravel.com/api/5.7/Illuminate/Foundation/Testing/TestCase.html#method_seed

このメソッドでは、$this->seed('MySeederName');を呼び出してシーダーを起動するだけです。

したがって、すべてのテストの前にこのシーダーを起動するには、次のsetUp関数をテストクラスに追加できます。

public function setUp()
{
    parent::setUp();
    $this->seed('MySeederName');
}

最終結果は次と同じです。

 $this->artisan('db:seed',['--class' => 'MySeederName'])

または

Artisan::call('db:seed', ['--class' => 'MySeederName'])

しかし、構文は少し簡潔です(私の意見では)。

3
Chris Schmitz

RefreshDatabaseテスト特性を使用している場合:

abstract class TestCase extends BaseTestCase
{
    use CreatesApplication, RefreshDatabase {
        refreshDatabase as baseRefreshDatabase;
    }

    public function refreshDatabase()
    {
        $this->baseRefreshDatabase();

        // Seed the database on every database refresh.
        $this->artisan('db:seed');
    }
}
1
Steve Bauman

ArtisanのネイティブDatabaseMigrationsおよびシーダー/移行方法をバイパスする場合の代替ソリューションを次に示します。独自の特性を作成して、データベースをシードできます。

namespace App\Traits;

use App\Models\User;
use App\Models\UserType;

trait DatabaseSetup 
{

    public function seedDatabase()
    {
        $user = $this->createUser();
    }

    public function createUser()
    {
        return factory(User::class)->create([
            'user_type_id' => function () {
                return factory(UserType::class)->create()->id;
            }
        ]);
    }

    public function getVar() {
        return 'My Data';
    }
}

次に、テストで次のように呼び出します。

use App\Traits\DatabaseSetup;

class MyAwesomeTest extends TestCase
{
    use DatabaseSetup;
    use DatabaseTransactions;

    protected $reusableVar;

    public function setUp()
    {
        parent::setUp();
        $this->seedDatabase();
        $this->reusableVar = $this->getVar();
    }

    /**
     * @test
     */
    public function test_if_it_is_working()
    {
        $anotherUser = $this->createUser();
        $response = $this->get('/');
        $this->seeStatusCode(200);
    }

}
0
JP Lew