如何为 Laravel 测试播种数据库迁移?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/42350138/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to seed database migrations for laravel tests?
提问by Jeff Puckett
Laravel's documentationrecommends using the DatabaseMigrations
trait for migrating and rolling back the database between tests.
Laravel 的文档建议使用DatabaseMigrations
trait 在测试之间迁移和回滚数据库。
use Illuminate\Foundation\Testing\DatabaseMigrations;
class ExampleTest extends TestCase
{
use DatabaseMigrations;
/**
* A basic functional test example.
*
* @return void
*/
public function testBasicExample()
{
$response = $this->get('/');
// ...
}
}
However, I've got some seed data that I would like to use with my tests. If I run:
但是,我有一些种子数据想用于我的测试。如果我运行:
php artisan migrate --seed
then it works for the first test, but it fails subsequent tests. This is because the trait rolls back the migration, and when it runs the migration again, it doesn't seed the database. How can I run the database seeds with the migration?
然后它适用于第一次测试,但它在后续测试中失败。这是因为 trait 会回滚迁移,并且当它再次运行迁移时,它不会为数据库做种子。如何通过迁移运行数据库种子?
回答by lasec0203
All you need to do is make an artisan call db:seed
in the setUp function
您需要做的就是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('/');
// ...
}
}
ref: https://laravel.com/docs/5.6/testing#creating-and-running-tests
参考:https: //laravel.com/docs/5.6/testing#creating-and-running-tests
回答by Jeff Puckett
It took me some digging to figure this out, so I thought I'd share.
我花了一些时间才弄清楚这一点,所以我想我会分享.
If you look at the source code for the DatabaseMigrations
trait, then you'll see it has one function runDatabaseMigrations
that's invoked by setUp
which runs before every testand registers a callback to be run on teardown.
如果你看一下在源代码DatabaseMigrations
特质,那么你会看到它有一个功能,runDatabaseMigrations
即通过真实援引setUp
其运行每次测试之前并注册要在拆解运行的回调。
You can sort of "extend" the traitby aliasing that function, re-declare a new function with your logic in it (artisan db:seed
) under the original name, and call the alias inside it.
您可以通过为该函数添加别名来“扩展”特征,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('/');
// ...
}
}
回答by Chris Schmitz
I know this question has already been answered several times, but I didn't see this particular answer so I thought I'd throw it in.
我知道这个问题已经回答了好几次了,但是我没有看到这个特定的答案,所以我想我会把它扔进去。
For a while in laravel (at least since v5.5), there's been a method in the TestCase
class specifically used for calling a database seeder:
有一段时间在 laravel 中(至少从 v5.5 开始),类中有一个方法TestCase
专门用于调用数据库播种器:
https://laravel.com/api/5.7/Illuminate/Foundation/Testing/TestCase.html#method_seed
https://laravel.com/api/5.7/Illuminate/Foundation/Testing/TestCase.html#method_seed
with this method, you just need to call $this->seed('MySeederName');
to fire the seeder.
使用此方法,您只需要调用$this->seed('MySeederName');
以启动播种机。
So if you want this seeder to fire before every test, you can add the following setUp function to your test class:
因此,如果您希望此播种机在每次测试之前启动,您可以将以下 setUp 函数添加到您的测试类中:
public function setUp()
{
parent::setUp();
$this->seed('MySeederName');
}
The end result is the same as:
最终结果是一样的:
$this->artisan('db:seed',['--class' => 'MySeederName'])
or
或者
Artisan::call('db:seed', ['--class' => 'MySeederName'])
But the syntax is a bit cleaner (in my opinion).
但是语法更简洁(在我看来)。
回答by Steve Bauman
If you're using the RefreshDatabase
testing trait:
如果您正在使用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');
}
}
回答by JP Lew
Here is an alternate solution, in case you prefer to bypass Artisan's native DatabaseMigrations and seeder/migration methods. You can create your own trait to seed your database:
如果您更喜欢绕过 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';
}
}
Then call it in your test like this:
然后像这样在你的测试中调用它:
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);
}
}