Как посеять миграцию базы данных для тестов 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

то он работает для первого теста, но он не дает последующих тестов. Это связано с тем, что этот признак откатывает миграцию, и когда он снова запускает миграцию, он не засевает базу данных. Как запустить семена базы данных с помощью миграции?

Ответ 1

Все, что вам нужно сделать, это сделать вызов ремесленника 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

Ответ 2

Мне потребовалось некоторое время, чтобы понять это, поэтому я думал, что поделюсь.

Если вы посмотрите на исходный код для runDatabaseMigrations DatabaseMigrations, вы увидите, что у него есть одна функция runDatabaseMigrations, вызываемая setUp которая запускается перед каждым тестом и регистрирует обратный вызов для запуска при отрыве.

Вы можете "расширить" эту черту путем наложения этой функции, повторно объявить новую функцию с вашей логикой в ней (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('/');

        // ...
    }
}

Ответ 3

Я знаю, что на этот вопрос уже отвечали несколько раз, но я не видел этот конкретный ответ, поэтому подумал, что я его добавлю.

Какое-то время в 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'])

Но синтаксис немного чище (на мой взгляд).

Ответ 4

Если вы используете тестовую черту 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');
    }
}

Ответ 5

Вот альтернативное решение, если вы предпочитаете обходить собственные методы DatabaseMigrations и сеялки/миграции Artisan. Вы можете создать свою собственную черту, чтобы засеять вашу базу данных:

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);
    }

}