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