Skip to content

Instantly share code, notes, and snippets.

@ilzrv
Forked from Alymosul/README.md
Created August 11, 2019 17:48
Show Gist options
  • Save ilzrv/0f8e407d0f4229d0bac462c33ac8353b to your computer and use it in GitHub Desktop.
Save ilzrv/0f8e407d0f4229d0bac462c33ac8353b to your computer and use it in GitHub Desktop.
[Laravel] Seeding data in testing as part of the application build.

SeedDatabase trait along with SeedDatabaseState class gives your Laravel project the ability to seed the testing database once before running the full suite tests, which improves the speed of the tests than seeding the testing database before each test.

Also, it has the option to run custom seeders instead of the seeders that are called in the run() method of the DatabaseSeeder class you can achieve that as follows

...in the Testcase.php

public function setUp()
{
    parent::setUp();
    SeedDatabaseState::$seeders = [RolesSeeder::class, PermissionSeeder::class];
    $this->seedDatabase();
}

Instructions:

  • Place the SeedDatabase.php and the SeedDatabaseState.php into the tests folder in your Laravel project and update the TestCase.php to use the SeedDatabase trait and make the changes in the setup() method to call $this->seedDatabase(); after calling the parent::setup()
<?php
namespace Tests;
use Illuminate\Database\Seeder;
use Illuminate\Contracts\Console\Kernel;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Foundation\Testing\RefreshDatabase;
trait SeedDatabase
{
/**
* Seeds the database.
*
* @return void
*/
public function seedDatabase()
{
if (! SeedDatabaseState::$seeded) {
$this->runSeeders(SeedDatabaseState::$seeders);
$this->syncTransactionTraits();
if (SeedDatabaseState::$seedOnce) {
SeedDatabaseState::$seeded = true;
}
}
}
/**
* Calls specific seeders if possible.
*
* @param array $seeders
*/
public function runSeeders(array $seeders)
{
if (empty($seeders)) {
$this->artisan('db:seed');
$this->app[Kernel::class]->setArtisan(null);
return;
}
$this->getSeederInstance()->call($seeders);
}
/**
* Persists the seed and begins a new transaction
* where the rollback has been already registered in Transaction traits.
*
* @return void
*/
public function syncTransactionTraits()
{
$uses = array_flip(class_uses_recursive(static::class));
if (isset($uses[RefreshDatabase::class]) || isset($uses[DatabaseTransactions::class])) {
$database = $this->app->make('db');
foreach ($this->connectionsToTransact() as $name) {
$database->connection($name)->commit();
$database->connection($name)->beginTransaction();
}
}
}
/**
* Builds a quick seeder instance.
*
* @return Seeder
*/
private function getSeederInstance()
{
return
new class() extends Seeder {
public function run()
{
}
};
}
}
<?php
namespace Tests;
class SeedDatabaseState
{
/**
* Indicates if the test database has been seeded.
*
* @var bool
*/
public static $seeded = false;
/**
* Indicates if the seeders should run once at the beginning of the suite.
*
* @var bool
*/
public static $seedOnce = true;
/**
* Runs only these registered seeders instead of running all seeders.
*
* @var array
*/
public static $seeders = [];
}
<?php
namespace Tests;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
abstract class TestCase extends BaseTestCase
{
use CreatesApplication, RefreshDatabase, SeedDatabase;
public function setUp()
{
parent::setUp();
$this->seedDatabase();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment