LiipTestFixturesBundle: [SF 5.3] Impossible to make functionnal test with SQLite: Operation 'AbstractPlatform::getListDatabasesSQL' is not supported by platform.

Preconditions

My dependencies on a fresh Symfony app are:

"require": {
    "php": ">=7.4",
    "ext-ctype": "*",
    "ext-iconv": "*",
    "composer/package-versions-deprecated": "1.11.99.4",
    "doctrine/doctrine-bundle": "^2.4",
    "doctrine/doctrine-migrations-bundle": "^3.2",
    "doctrine/orm": "^2.10",
    "symfony/console": "5.3.*",
    "symfony/dotenv": "5.3.*",
    "symfony/flex": "^1.3.1",
    "symfony/framework-bundle": "5.3.*",
    "symfony/proxy-manager-bridge": "5.3.*",
    "symfony/runtime": "5.3.*",
    "symfony/yaml": "5.3.*"
},
"require-dev": {
    "dama/doctrine-test-bundle": "^6.6",
    "doctrine/doctrine-fixtures-bundle": "^3.4",
    "liip/test-fixtures-bundle": "^2.0.0",
    "phpunit/phpunit": "^9.5",
    "symfony/browser-kit": "5.3.*",
    "symfony/css-selector": "5.3.*",
    "symfony/maker-bundle": "^1.34",
    "symfony/phpunit-bridge": "^5.3"
},
  1. PHP 7.4 & PHP 8
  2. Symfony 5.3

Steps to reproduce

  1. Install a fresh symfony application
symfony new app
cd app
composer require --dev phpunit/phpunit symfony/test-pack
  1. Create a WebTestCase in app/tests/DummyFunctionnalTest.php
  2. Install Doctrine and the maker bundle
composer require symfony/orm-pack
composer require --dev symfony/maker-bundle
  1. Set the DATABASE_URL in the .env.test file :
DATABASE_URL="sqlite:///%kernel.project_dir%/var/app.db"
  1. Create an entity with the maker
  2. Create a fixture that creates an entity
class PostFixtures extends Fixture
{
    public function load(ObjectManager $manager): void
    {
        $post = new Post();

        $post->setTitle("Titre");
        $post->setContent("Contenu");
        $post->setCreatedAt(new DateTimeImmutable());

        $manager->persist($post);
        $manager->flush();
    }
}
  1. Install LiipTestFixturesBundle:
composer require --dev liip/test-fixtures-bundle:^2.0.0
  1. Write a test :
class DummyFunctionalTest extends WebTestCase
{
    protected KernelBrowser $client;
    private AbstractDatabaseTool $databaseTool;

    protected function setUp(): void
    {
        parent::setUp();

        $this->client = static::createClient();
        $this->databaseTool = $this->client->getContainer()->get(DatabaseToolCollection::class)->get();
    }

    public function testDummy(): void
    {
        $this->databaseTool->loadFixtures([PostFixtures::class]);

        $this->assertNotNull($this->client->getContainer()->get(PostRepository::class)->findAll());
    }
}
  1. Run the tests

Expected result

  1. I expect the test to run and reach the assert statement

Actual result

I got this error when I run tests:

./bin/phpunit
PHPUnit 9.5.10 by Sebastian Bergmann and contributors.

Testing 
E                                                                   1 / 1 (100%)

Time: 00:00.100, Memory: 16.00 MB

There was 1 error:

1) App\Tests\DummyIntegrationTest::testDummy
Doctrine\DBAL\Exception: Operation 'Doctrine\DBAL\Platforms\AbstractPlatform::getListDatabasesSQL' is not supported by platform.

/app/vendor/doctrine/dbal/src/Exception.php:22
/app/vendor/doctrine/dbal/src/Platforms/AbstractPlatform.php:2749
/app/vendor/doctrine/dbal/src/Schema/AbstractSchemaManager.php:102
/app/vendor/liip/test-fixtures-bundle/src/Services/DatabaseTools/ORMDatabaseTool.php:163
/app/vendor/liip/test-fixtures-bundle/src/Services/DatabaseTools/ORMDatabaseTool.php:60
/app/tests/DummyFunctionalTest.php:27

ERRORS!
Tests: 1, Assertions: 0, Errors: 1.

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Reactions: 1
  • Comments: 42 (2 by maintainers)

Most upvoted comments

@ndench thanks, this PR was merged.

Please try the last release: https://github.com/liip/LiipTestFixturesBundle/releases/tag/2.3.0

Same issue, but with

"doctrine/doctrine-bundle": "2.6.0",
Testing /home/www/app/tests/Functional/Infrastructure/Download

Doctrine\DBAL\Exception : Operation 'Doctrine\DBAL\Platforms\AbstractPlatform::getListDatabasesSQL' is not supported by platform.
 /home/www/app/vendor/doctrine/dbal/src/Exception.php:22
 /home/www/app/vendor/doctrine/dbal/src/Platforms/AbstractPlatform.php:3059
 /home/www/app/vendor/doctrine/dbal/src/Schema/AbstractSchemaManager.php:115
 /home/www/app/vendor/liip/test-fixtures-bundle/src/Services/DatabaseTools/ORMDatabaseTool.php:163
 /home/www/app/vendor/liip/test-fixtures-bundle/src/Services/DatabaseTools/ORMDatabaseTool.php:60
 /home/www/app/tests/Functional/FixtureTestCase.php:37
 /home/www/app/tests/Functional/Infrastructure/Download/RequestDownloadBuilderTest.php:39

It appears that DoctrineBundle 2.6.0 now injects middlewares all the time (https://github.com/doctrine/DoctrineBundle/pull/1472/files#diff-36d403fbfadb131317c08db172ddbb7844ce35323d45c6096043b97ed066b60a)? I stepped through the code and even though I have both logging: false and profiling: false in my config/test/doctrine.yaml it’s still injecting the LoggingMiddleware.

I’m not sure that we need to rewrite how the database is detected as much as we need to figure out how to disable the middlewares in the test environment? From what I can see, there’s no way to remove them. If a MiddlewareInterface exists it’s auto tagged and auto injected.

@flohw This is only relevant if you have a dependency on sentry/sentry-symfony:

Sentry can collect performance information which include database performance. To do this they need to decorate the database abstraction, which seems to cause the issue. This is enabled by default and can be deactivated in the configuration:

# config/packages/sentry.yaml
sentry:
    tracing:
        enabled: false

As SQLite seems to work on unique database this should not be possible to list databases. Thus a way to handle it could be creating the database anyway in a Sqlite context, kinda like this (that works in this specific case):

protected function createDatabaseIfNotExists(): void
{
    $params = $this->connection->getParams();
    if (isset($params['master'])) {
        $params = $params['master'];
    }
    $dbName = $params['dbname'] ?? '';

    unset($params['dbname'], $params['url']);

    // Unset url to avoid issue:
    // “An exception occurred in driver: SQLSTATE[HY000] [1049] Unknown database 'test'”

    $tmpConnection = DriverManager::getConnection($params);
    $tmpConnection->connect();
    
    $databases = $tmpConnection->getDatabasePlatform() instanceof SqlitePlatform
        ? ['']
        : $tmpConnection->getSchemaManager()->listDatabases();

    if (!\in_array($dbName, $databases, true)) {
        $tmpConnection->getSchemaManager()->createDatabase($dbName);
    }

    $tmpConnection->close();
}

EDIT: I ended testing it by forking the repo and it seems it does not break the actual tests suite

Ok, I lied. After a bit more investigation I’ve found another way we can detect the type of database. Created PR #176 to fix it. If you’re having this issue please install my fork and let me know if it works for you.

I’m sorry I missed your comment.

I’m not familiar with how the driver is loaded, it’s still black magic for me. Feel free to submit a PR if you have an idea.

@alexislefebvre yes, I mentioned it in comment yesterday 😅

It seems that getDriverName() in DatabaseTool is just a string 👇 https://github.com/liip/LiipTestFixturesBundle/blob/2.x/src/Services/DatabaseTools/ORMSqliteDatabaseTool.php#L37-L40 Then can’t we use DatabasePlatform not DriverName to resolve appropriate DatabaseTool here?

I’m not familiar with PHPCR and MongoDBODM, so I thought why not use DatabasePlatform to distinguish db type…

I found one difference while using different versions of doctrine/doctrine-bundle, on this line:

https://github.com/liip/LiipTestFixturesBundle/blob/90a963021ba3a031e3371eb6b1168c9c41dc6ea7/src/Services/DatabaseToolCollection.php#L50

With v2.6.0 it returns Doctrine\DBAL\Logging\Driver. With v2.5.7 it returns Doctrine\DBAL\Driver\PDO\MySQL\Driver.

With 2.6.0, it won’t find the item for SQLite in the following nice, so it returns the default configuration, and the ORMSqliteDatabaseTool is not used when it should have been.

We have to rewrite how the type of database is detected, because Doctrine\DBAL\Logging\Driver is hiding it.

FYI I am having the same issue with:

  • symfony/framework-bundle 5.3.10
  • doctrine/dbal 3.1.4
  • liip/test-fixtures-bundle 2.1.0
  • liip/functional-test-bundle 4.4.3

Note that I’m not using DAMADoctrineBundle but changing keep_database_and_schema to true + re-creating the SQLite database before running the tests fixed it 👍

liip_test_fixtures:
    cache_db:
        sqlite: 'Liip\TestFixturesBundle\Services\DatabaseBackup\SqliteDatabaseBackup'
    keep_database_and_schema: true
    cache_metadata: true