LaravelSqliteTestDatabaseTestingPHP

March 19, 2023

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

By Vladimir Nikolic

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

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.

Are you set to create something extraordinary?

Ready to take the next step? Let's work together to transform your ideas into reality. Contact us today to discuss how we can help you create impactful, user-centered solutions that drive success.

Contact Us