symfonydoctrinesymfony4functional-testingliipfunctionaltestbundle

Functional Testing Symfony with mulitple Doctrine EntityManagers


In a Symfony 4 application I have configured multiple entity managers. I want my functional tests to automatically create DB tables for both managers.

However, when I run my test; PHP unit encounters an error that says

PDOException: SQLSTATE[42S02]: Base table or view not found: 1146 Table 'test.example' doesn't exist

config/packages/doctrine.yaml:

doctrine:
    dbal:
        connections:
            default:
                url: '%env(resolve:DATABASE_URL)%'
                driver: 'pdo_mysql'
                server_version: '5.7'
                charset: utf8mb4
            custom:
                url: '%env(resolve:DATABASE_URL)%'
                driver: 'pdo_mysql'
                server_version: '5.7'
                charset: utf8mb4

    orm:
        default_entity_manager: default
        auto_generate_proxy_classes: '%kernel.debug%'
        entity_managers:
            default:
                connection: default
                naming_strategy: doctrine.orm.naming_strategy.underscore
                auto_mapping: true
                mappings:
                    Model:
                        is_bundle: false
                        type: annotation
                        dir: '%kernel.project_dir%/src/Entity/Model'
                        prefix: 'App\Entity\Model'
                        alias: Model
            custom:
                connection: custom
                naming_strategy: doctrine.orm.naming_strategy.underscore
                mappings:
                    Custom:
                        is_bundle: false
                        type: annotation
                        dir: '%kernel.project_dir%/src/Entity/Custom'
                        prefix: 'App\Entity\Custom'
                        alias: Custom

To create tables and load Fixtures I'm currently using the Liip Functional Test Bundle.

A simple test looks like this:

tests\Functional\GeneralControllerTest.php:

class GeneralControllerTest extends WebTestCase
{
    /**
     * {@inheritdoc}
     */
    protected function setUp()
    {
        $this->loadFixtures([
            SomeFixtures::class,
            MoreFixtures::class,
        ]);
    }

    /**
     * @dataProvider providePageUris
     * @test
     * @param string $uri
     */
    public function checkThatPageLoads($uri)
    {
        $client = static::createClient();

        /* ... more code ... */

        $client->request(Request::METHOD_GET, $uri);

        static::assertEquals(Response::HTTP_OK, $client->getResponse()->getStatusCode());
    }

    /**
     * @return array
     */
    public function providePageUris()
    {
        return [
            ["/dashboard"],
        ];
    }
}

How can I make my Test Case create database tables for the other custom Doctrine EntityManagers?

I have tried adding:

$this->loadFixtures([], true, "custom");

and also:

$this->runCommand("doctrine:schema:create --env=test --em=custom");

to the setUp() method of the Test Case, but this did not result in what is needed. The database tables all need to be created before any Fixture is loaded into the database.


Solution

  • To not have tables in a different entity manager and connection removed when loading data fixtures I changed the doctrine configuration with distinct environment variables.

    config/packages/doctrine.yaml:

    doctrine:
        dbal:
            connections:
                default:
                    url: '%env(resolve:DATABASE_URL)%'
                    driver: 'pdo_mysql'
                    server_version: '5.7'
                    charset: utf8mb4
                custom:
                    url: '%env(resolve:DATABASE_URL_CUSTOM)%'
                    driver: 'pdo_mysql'
                    server_version: '5.7'
                    charset: utf8mb4