Skip to content

Instantly share code, notes, and snippets.

@adamwathan
Last active January 24, 2024 20:28
Show Gist options
  • Save adamwathan/dd46a8501097942a771925c02bac0111 to your computer and use it in GitHub Desktop.
Save adamwathan/dd46a8501097942a771925c02bac0111 to your computer and use it in GitHub Desktop.
A Better Database Testing Workflow in Laravel
<?php
use Illuminate\Contracts\Console\Kernel;
trait DatabaseSetup
{
protected static $migrated = false;
public function setupDatabase()
{
if ($this->isInMemory()) {
$this->setupInMemoryDatabase();
} else {
$this->setupTestDatabase();
}
}
protected function isInMemory()
{
return config('database.connections')[config('database.default')]['database'] == ':memory:';
}
protected function setupInMemoryDatabase()
{
$this->artisan('migrate');
$this->app[Kernel::class]->setArtisan(null);
}
protected function setupTestDatabase()
{
if (! static::$migrated) {
$this->artisan('migrate:refresh');
$this->app[Kernel::class]->setArtisan(null);
static::$migrated = true;
}
$this->beginDatabaseTransaction();
}
public function beginDatabaseTransaction()
{
$database = $this->app->make('db');
foreach ($this->connectionsToTransact() as $name) {
$database->connection($name)->beginTransaction();
}
$this->beforeApplicationDestroyed(function () use ($database) {
foreach ($this->connectionsToTransact() as $name) {
$database->connection($name)->rollBack();
}
});
}
protected function connectionsToTransact()
{
return property_exists($this, 'connectionsToTransact')
? $this->connectionsToTransact : [null];
}
}
<?php
abstract class TestCase extends Illuminate\Foundation\Testing\TestCase
{
use DatabaseSetup;
/**
* The base URL to use while testing the application.
*
* @var string
*/
protected $baseUrl = 'http://localhost';
protected function setUp()
{
parent::setUp();
$this->setupDatabase();
}
/**
* Creates the application.
*
* @return \Illuminate\Foundation\Application
*/
public function createApplication()
{
$app = require __DIR__.'/../bootstrap/app.php';
$app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();
return $app;
}
}
@alies-dev
Copy link

Note that Laravel has a build in trait \Illuminate\Foundation\Testing\RefreshDatabase (formerly added as FreshDatabase) that has the same logic

@AlexP11223
Copy link

Yeah, looks like it's not needed anymore in recent Laravel versions.

@Shymoney
Copy link

awesome

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment