如何为laravel测试提供数据库迁移的种子?

Jef*_*ett 16 php testing laravel laravel-seeding laravel-migrations

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('/');

        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,我有一些种子数据,我想用我的测试.如果我跑:

php artisan migrate --seed
Run Code Online (Sandbox Code Playgroud)

然后它适用于第一次测试,但它无法进行后续测试.这是因为特征回滚了迁移,当它再次运行迁移时,它不会为数据库设定种子.如何通过迁移运行数据库种子?

Jef*_*ett 21

我花了一些时间来解决这个问题,所以我想我会分享.

如果你查看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('/');

        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 这应该在测试文档中!播种可能是测试中非常重要的一部分,我没有看到任何提及.如我错了请纠正我. (7认同)

las*_*203 20

您需要做的就是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('/');

        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

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

  • 另外,你可以在`setUp()`方法中调用`$this-&gt;seed()`。 (4认同)
  • 有没有办法在课堂测试中而不是在每次测试之前做到这一点?我尝试了 `setUpBeforeClass()`,但它是一个静态函数,由于静态特性,我无法播种和做我需要的一切......当你需要运行一个一堆不需要完全重置数据库的测试(这对单元测试不利)。 (2认同)

Chr*_*itz 15

我知道这个问题已经回答了好几次了,但我没有看到这个特定的答案,所以我想我会把它扔进去。

在 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');
}
Run Code Online (Sandbox Code Playgroud)

最终结果与以下相同:

 $this->artisan('db:seed',['--class' => 'MySeederName'])
Run Code Online (Sandbox Code Playgroud)

或者

Artisan::call('db:seed', ['--class' => 'MySeederName'])
Run Code Online (Sandbox Code Playgroud)

但是语法更简洁(在我看来)。


Sai*_*Sai 13

使用 Laravel 8,如果您使用RefreshDatabasetrait,则可以使用以下命令从测试用例中调用播种:

use Illuminate\Foundation\Testing\RefreshDatabase;

class ExampleTest extends TestCase
{
    use RefreshDatabase;

    /**
     * A basic functional test example.
     *
     * @return void
     */
    public function testBasicExample()
    {
        // Run the DatabaseSeeder...
        $this->seed();

        // Run a specific seeder...
        $this->seed(OrderStatusSeeder::class);

        $response = $this->get('/');

        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

有关更多信息/示例,请参阅文档:https : //laravel.com/docs/8.x/database-testing#running-seeders

  • 您还可以使用“protected bool $seed = true;”在所有测试之前播种一次 (7认同)

小智 13

在 Laravel 8 中,RefreshDatabase 现在正在寻找一个名为“seed”的布尔属性。

    /** 
     * Illuminate\Foundation\Testing\RefreshDatabase
     * Determine if the seed task should be run when refreshing the database.
     *
     * @return bool
     */
    protected function shouldSeed()
    {
        return property_exists($this, 'seed') ? $this->seed : false;
    }
Run Code Online (Sandbox Code Playgroud)

如果您希望播种,只需为您的测试类提供受保护的属性 $seed 并将其设置为 true 即可。

class ProjectControllerTest extends TestCase
{

    protected $seed = true;
    public function testCreateProject()
    {
        $project = Project::InRandomOrder()->first();
        $this->assertInstanceOf($project,Project::class);
    }
Run Code Online (Sandbox Code Playgroud)

此方法的优点在于,单个测试不会在每次运行时都播种。只有种子必要的测试才会构建数据库。


Ste*_*man 5

如果您正在使用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');
    }
}
Run Code Online (Sandbox Code Playgroud)