Run tests against in-memory sqlite and refuse real databases

The :memory: overrides in phpunit.xml had been commented out since 2024,
so RefreshDatabase ran migrate:fresh against the real .env database and
wiped it on every local test run. Enable the overrides, let the special
:memory: identifier bypass database_path() resolution and the boot-time
touch(), and add a TestCase guard that aborts the suite unless it is
pointed at in-memory sqlite.

ItemExportTest only ever passed by reading the populated dev database;
seed the root dashboard item it depends on so it passes on a fresh DB.
This commit is contained in:
KodeStar
2026-07-09 10:52:17 +01:00
parent 6f932918aa
commit 2555ab1b3c
5 changed files with 61 additions and 6 deletions
+3 -2
View File
@@ -150,9 +150,10 @@ class AppServiceProvider extends ServiceProvider
$db_type = config()->get('database.default');
if ($db_type == 'sqlite') {
$db_file = database_path(env('DB_DATABASE', 'app.sqlite'));
$db_file = config()->get('database.connections.sqlite.database');
Log::debug('SQLite Database Path: ' . $db_file);
if (! is_file($db_file)) {
// Do not create a file for the in-memory database identifier.
if ($db_file !== ':memory:' && ! is_file($db_file)) {
touch($db_file);
}
}
+5 -1
View File
@@ -7,7 +7,11 @@ return [
'connections' => [
'sqlite' => [
'driver' => 'sqlite',
'database' => database_path(env('DB_DATABASE', 'app.sqlite')), // Make sure to use the correct path
// Use the correct path, but let the special in-memory identifier
// pass through untouched so tests can run against ':memory:'.
'database' => env('DB_DATABASE', 'app.sqlite') === ':memory:'
? ':memory:'
: database_path(env('DB_DATABASE', 'app.sqlite')),
'prefix' => '',
'foreign_key_constraints' => env('DB_FOREIGN_KEYS', true), // Enable foreign key constraints
],
+2 -2
View File
@@ -12,8 +12,8 @@
<env name="APP_ENV" value="testing"/>
<env name="BCRYPT_ROUNDS" value="4"/>
<env name="CACHE_STORE" value="array"/>
<!-- <env name="DB_CONNECTION" value="sqlite"/> -->
<!-- <env name="DB_DATABASE" value=":memory:"/> -->
<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value=":memory:"/>
<env name="MAIL_MAILER" value="array"/>
<env name="PULSE_ENABLED" value="false"/>
<env name="QUEUE_CONNECTION" value="sync"/>
+13
View File
@@ -5,6 +5,7 @@ namespace Tests\Feature;
use App\Item;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Date;
use Illuminate\Support\Facades\DB;
use Tests\TestCase;
class ItemExportTest extends TestCase
@@ -39,6 +40,18 @@ class ItemExportTest extends TestCase
public function test_exports_assigned_tag_titles_excluding_the_root_tag(): void
{
// Mirror the root/default dashboard row that production seeds (id 0),
// so the item_tag pivot's foreign key to items.id is satisfied on a
// fresh in-memory database.
DB::table('items')->insert([
'id' => 0,
'title' => 'app.dashboard',
'url' => '',
'type' => 1,
'user_id' => 0,
'pinned' => 0,
]);
$item = Item::factory()
->create([
'title' => 'Tagged Item',
+38 -1
View File
@@ -6,5 +6,42 @@ use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
abstract class TestCase extends BaseTestCase
{
//
protected function setUp(): void
{
parent::setUp();
$this->guardAgainstRealDatabase();
}
/**
* Refuse to run the test suite against anything other than an
* in-memory SQLite database.
*
* The suite uses RefreshDatabase (migrate:fresh), which would wipe
* whatever database it is pointed at. The only supported test
* configuration for this repo is sqlite + ':memory:'. Any other
* connection (a real sqlite file, mysql, pgsql, ...) is rejected so
* we can never destroy real data.
*/
private function guardAgainstRealDatabase(): void
{
$default = config('database.default');
$driver = config("database.connections.{$default}.driver");
$database = config("database.connections.{$default}.database");
if ($driver === 'sqlite' && $database === ':memory:') {
return;
}
throw new \RuntimeException(sprintf(
'Refusing to run tests: the default database connection (%s) is '
. 'driver "%s" pointing at "%s". Tests only run against an '
. 'in-memory SQLite database (driver "sqlite", database ":memory:") '
. 'to avoid wiping real data via RefreshDatabase. Check phpunit.xml '
. 'DB_CONNECTION/DB_DATABASE overrides.',
$default,
$driver,
is_scalar($database) ? (string) $database : gettype($database)
));
}
}