Skip to main content

Test your Doctrine2 metadata mapping configuration

·2 mins

I use the Doctrine2 Object Relational Mapper as abstraction layer between my model and database. I use PHPUnit to unit test my code, but if the configuration is incorrect the code won't work like intended and the Doctrine2 ORM will fail with exceptions as result. To ensure the configuration is correct I created a test to validate my configuration.

The test

<?php

final class SchemaValidationTest extends PHPUnit_Framework_TestCase
{
    public function test_valid_doctrine_schema()
    {
        $driver = new \Doctrine\ORM\Mapping\Driver\SimplifiedYamlDriver([
            __DIR__ . '/../src/Resources/doctrine/mapping' => 'Acme\Lib' // directory => namespace prefix
        ]);

        $config = \Doctrine\ORM\Tools\Setup::createConfiguration(true);
        $config->setMetadataDriverImpl($driver);

        $em = \Doctrine\ORM\EntityManager::create(['url' => 'sqlite:///schema-validation.sqlite'], $config);

        $validator = new \Doctrine\ORM\Tools\SchemaValidator($em);

        $errors = $validator->validateMapping();

        if (count($errors) > 0) {
            $message = PHP_EOL;
            foreach ($errors as $class => $classErrors) {
                $message .= "- " . $class . ":" . PHP_EOL . implode(PHP_EOL, $classErrors) . PHP_EOL . PHP_EOL;
            }
            $this->fail($message);
        }
    }
}

First I had to create a driver to read the metadata mapping configuration. I used the SimplifiedYamlDriver (donated and used by Symfony) to be compatible with the Symfony2 framework (file extension: .orm.yml instead of .dcm.yml). You can also use the more generic YamlDriver. The SimplifiedYamlDriver expects an array with the location of the configuration files as key and the prefix namespace as value.

Then I created a configuration with development enabled to prevent the creation of Proxy classes (Stackoverflow) and set the previously created driver as metadata driver.

Now you're ready to initiate an EntityManager. I used a SQLite connection because a connection is required by the EntityManager. The second parameter is the configuration.

At last, the SchemaValidator tool should be initiated. The SchemaValidator validates the mapping and returns an array of errors which I count to determine if the the test should succeed or fail.

Done! The continuous integration tool I'm using will run all tests, including this one, at every push and failing configurations belong to the past.