Laravel and Pest unit testing with SQLite And Foreign Key issue on SQLite

Vladimir Nikolic
February 14th, 2023
Running php tests on Laravel is breeze. You simply run php artisan test
command.
However if you are testing database, you have two options. One is to create yor testing database and another is to use SQLite in memory.
I did not want to have whole team to create new mariadb database on their machines, so decided to use SQLite for the testing.
To use SQLite for testing in Laravel applicaiton we need to tell phpunit.xml to use it.
So, in phpunit.xml add/change those two lines:
<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value=":memory:"/>
Problem i faced is that SQLite was not able to work with foreign keys in laravel migrations.
BadMethodCallException : SQLite doesn't support dropping foreign keys (you would need to re-create the table).
To solve it i had to update code in TestCase.php
namespace Tests;
use Closure;
use Illuminate\Database\Connection;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Schema\SQLiteBuilder;
use Illuminate\Database\SQLiteConnection;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use Illuminate\Support\Fluent;
abstract class TestCase extends BaseTestCase
{
use CreatesApplication;
public function __construct(?string $name = null, array $data = [], string $dataName = '')
{
$this->resolveSqlite();
parent::__construct($name, $data, $dataName);
}
public function resolveSqlite()
{
Connection::resolverFor('sqlite',
function ($connection, $database, $prefix, $config) {
return new class($connection, $database, $prefix, $config)
extends SQLiteConnection {
public function getSchemaBuilder()
{
if ($this->schemaGrammar === null) {
$this->useDefaultSchemaGrammar();
}
return new class($this) extends SQLiteBuilder {
protected function createBlueprint($table, Closure $callback = null)
{
return new class($table, $callback) extends Blueprint {
public function dropForeign($index)
{
return new Fluent();
}
};
}
};
}
};
});
}
}
This will solve BadMethodCallException : SQLite doesn't support dropping foreign keys (you would need to re-create the table).
error.