Skip to content

Instantly share code, notes, and snippets.

@dannetstudio
Forked from Alymosul/README.md
Last active November 10, 2020 07:02
Show Gist options
  • Select an option

  • Save dannetstudio/7e8df759f8f734e8f8bc9941f93bc7d5 to your computer and use it in GitHub Desktop.

Select an option

Save dannetstudio/7e8df759f8f734e8f8bc9941f93bc7d5 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;
protected function setUp(): void
{
parent::setUp();
$this->seedDatabase();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment