Database
Testing
PHP
Laravel
Sqlite
Test

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

by Vladimir Nikolic, CEO Coding Wisely

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 application we need to tell phpunit.xml to use it.

So, in phpunit.xml add/change those two lines:

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.

About the Author:

Vladimir, with over 25 years in the software industry, serves as the CEO of Coding Wisely.

Disclaimer:

The information provided in this article is based on the author's knowledge and experience as of the publication date. Technology and tools may have evolved since then. Always refer to the official documentation for the latest instructions and updates.