如何为 laravel 测试播种数据库迁移?
How to seed database migrations for laravel tests?
Laravel 的 documentation 建议使用 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
然后它适用于第一次测试,但它无法通过后续测试。这是因为 trait 回滚迁移,并且当它 运行 再次迁移时,它不会为数据库播种。我如何 运行 迁移数据库种子?
我花了一些时间才弄明白,所以 I thought I'd share。
如果您查看 DatabaseMigrations
trait, then you'll see it has one function runDatabaseMigrations
that's invoked by setUp
which runs before every test 的源代码并在拆卸时注册一个回调 运行。
您可以通过为该函数添加别名来排序 "extend" the trait,re-declare 一个包含您的逻辑的新函数 (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('/');
// ...
}
}
如果您更愿意绕过 Artisan 的原生 DatabaseMigrations 和 seeder/migration 方法,这是一个替代解决方案。您可以创建自己的特征来为您的数据库播种:
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);
}
}
您需要做的就是在 setUp 函数中调用 artisan db:seed
<?php
use Illuminate\Foundation\Testing\DatabaseMigrations;
class ExampleTest extends TestCase
{
use DatabaseMigrations;
public function setUp(): void
{
parent::setUp();
// seed the database
$this->artisan('db:seed');
// alternatively you can call
// $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
我知道这个问题已经回答了好几次,但我没有看到这个特定的答案,所以我想我会把它扔进去。
在laravel中有一段时间(至少从v5.5开始),TestCase
class中有一个方法专门用于调用数据库播种器:
https://laravel.com/api/5.7/Illuminate/Foundation/Testing/TestCase.html#method_seed
使用此方法,您只需调用 $this->seed('MySeederName');
即可启动播种器。
因此,如果您希望此播种器在每次测试前触发,您可以将以下设置函数添加到您的测试中 class:
public function setUp()
{
parent::setUp();
$this->seed('MySeederName');
}
最终结果相同:
$this->artisan('db:seed',['--class' => 'MySeederName'])
或
Artisan::call('db:seed', ['--class' => 'MySeederName'])
但语法更简洁(在我看来)。
如果您使用 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');
}
}
使用 Laravel 8,如果您使用 RefreshDatabase
特征,您可以使用以下方法从您的测试用例中调用播种:
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('/');
// ...
}
}
有关更多信息,请参阅文档 information/examples:
https://laravel.com/docs/8.x/database-testing#running-seeders
对于 Laravel 8,RefreshDatabase 现在正在寻找一个名为“种子”的布尔值 属性。
/**
* 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;
}
只要给你的测试 class protected 属性 $seed,如果你想播种就把它设置为 true。
class ProjectControllerTest extends TestCase
{
protected $seed = true;
public function testCreateProject()
{
$project = Project::InRandomOrder()->first();
$this->assertInstanceOf($project,Project::class);
}
此方法的优点在于,单个测试不会每次都播种 运行。只有种子必要的测试才会建立数据库。
Laravel 的 documentation 建议使用 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
然后它适用于第一次测试,但它无法通过后续测试。这是因为 trait 回滚迁移,并且当它 运行 再次迁移时,它不会为数据库播种。我如何 运行 迁移数据库种子?
我花了一些时间才弄明白,所以 I thought I'd share。
如果您查看 DatabaseMigrations
trait, then you'll see it has one function runDatabaseMigrations
that's invoked by setUp
which runs before every test 的源代码并在拆卸时注册一个回调 运行。
您可以通过为该函数添加别名来排序 "extend" the trait,re-declare 一个包含您的逻辑的新函数 (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('/');
// ...
}
}
如果您更愿意绕过 Artisan 的原生 DatabaseMigrations 和 seeder/migration 方法,这是一个替代解决方案。您可以创建自己的特征来为您的数据库播种:
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);
}
}
您需要做的就是在 setUp 函数中调用 artisan db:seed
<?php
use Illuminate\Foundation\Testing\DatabaseMigrations;
class ExampleTest extends TestCase
{
use DatabaseMigrations;
public function setUp(): void
{
parent::setUp();
// seed the database
$this->artisan('db:seed');
// alternatively you can call
// $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
我知道这个问题已经回答了好几次,但我没有看到这个特定的答案,所以我想我会把它扔进去。
在laravel中有一段时间(至少从v5.5开始),TestCase
class中有一个方法专门用于调用数据库播种器:
https://laravel.com/api/5.7/Illuminate/Foundation/Testing/TestCase.html#method_seed
使用此方法,您只需调用 $this->seed('MySeederName');
即可启动播种器。
因此,如果您希望此播种器在每次测试前触发,您可以将以下设置函数添加到您的测试中 class:
public function setUp()
{
parent::setUp();
$this->seed('MySeederName');
}
最终结果相同:
$this->artisan('db:seed',['--class' => 'MySeederName'])
或
Artisan::call('db:seed', ['--class' => 'MySeederName'])
但语法更简洁(在我看来)。
如果您使用 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');
}
}
使用 Laravel 8,如果您使用 RefreshDatabase
特征,您可以使用以下方法从您的测试用例中调用播种:
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('/');
// ...
}
}
有关更多信息,请参阅文档 information/examples: https://laravel.com/docs/8.x/database-testing#running-seeders
对于 Laravel 8,RefreshDatabase 现在正在寻找一个名为“种子”的布尔值 属性。
/**
* 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;
}
只要给你的测试 class protected 属性 $seed,如果你想播种就把它设置为 true。
class ProjectControllerTest extends TestCase
{
protected $seed = true;
public function testCreateProject()
{
$project = Project::InRandomOrder()->first();
$this->assertInstanceOf($project,Project::class);
}
此方法的优点在于,单个测试不会每次都播种 运行。只有种子必要的测试才会建立数据库。