可以说明:架构:更新是否仅限于可用实体的子集?

时间:2016-04-10 19:31:18

标签: doctrine-orm phpunit symfony

我目前正在开发一个Symfony 3软件包,它具有生成一些锅炉板代码的功能。我想通过使用phpunit测试正确性。为此,我认为最好生成一些测试用例(其中将包含将具有@Entity注释的类的源代码)并且让Doctrine更新测试环境的数据库,仅使用执行所需的实体考试。之后,可以再次安全地删除相应的表格。

但我不知道这样做的简单方法。由于我的捆绑包可能有一天会被安装在一个不完整的项目中,所以我更倾向于在测试甚至失败时不必更新整个模式来测试这个捆绑包。

我知道Doctrine的l7-lb-controller-v0.5.2-ae0t2课程,但我想知道是否有更实用的解决方案?那里的问题是你可以用它创建表等但我想那时候不会有任何映射?

谷歌不是很有帮助,所以我怀疑我在这里偏离了“正常”用法。另外,如果我违反了我的方法中的任何最佳做法,或者我需要重新考虑我的设计,我想听听它。

要明确我想:

  • 使用@Entity(可能还有其他)注释生成一个类,这个我已经在做了
  • 让doctrine更新架构以仅包含这些类
  • 在下次执行时可以使用这些类的映射

感谢您的想法。

1 个答案:

答案 0 :(得分:0)

很难找到在独立软件包/库上使用doctrine进行数据库测试的良好实践。

所以,我会按照我的方式给你:

1)特定数据库

为此,您可以创建特定的配置文件,包括您的数据库配置,与您的其他环境使用的配置文件不同,或者只是在您的phpunit配置中define environment variables

在测试阶段创建临时数据库:

/**
 * Create database.
 */
public static function createDatabase($path)
{
    $config = [
        'driver'   => 'pdo_mysql',
        'host'     => '127.0.0.1',
        'user'     => 'forge',
        'password' => 'forge',
    ];

    $tmpConnection = \Doctrine\DBAL\DriverManager::getConnection($config);

    // If the db exists, do nothing
    if (in_array('db_name', $tmpConnection->getSchemaManager()->listDatabases())) {
        return;
    }

    // Create the db
    $tmpConnection->getSchemaManager()->createDatabase($GLOBALS['db_name']);

    $tmpConnection->close();
}

2)特定的映射

为此,你可以:

注意如果您需要生成它们,则在实体不存在时,您需要将测试标记为已跳过。

3)特定架构

您需要重现数据库连接(临时),在测试开始时创建模式并在结束时删除它。

最后两个阶段可以在精简版中恢复:

use Doctrine\DBAL\DriverManager;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Tools\SchemaTool;
use Doctrine\ORM\Tools\Setup;

/**
 * Database.
 */
class Db
{
    /** @var EntityManager */
    private $entityManager;

    /**
     * Create db schema.
     */
    public function createSchema() 
    {
        // Location(s) of your mapping
        $mappingPaths = ['Acme/Path/To/Entities', 'Acme/Second/Path/To/Entities', ...];

        // Db config, should be loaded from config files as previously said
        $config = [
            'dbname'   => 'project_test'
            'driver'   => 'pdo_mysql',
            'host'     => 127.0.0.1,
            'user'     => 'forge',
            'password' => 'forge',
        ];

        // Configure and load your mapping
        $metadataConfiguration = Setup::createAnnotationMetadataConfiguration($mappingPaths, true, null, null, false);

        // Create the EntityManager instance
        $em = EntityManager::create($config, $metadataConfiguration);

        $tool = new SchemaTool($em);
        $metadata = $em->getMetaDataFactory()->getAllMetaData();

        // Drop an eventual existing schema
        $tool->dropSchema($metadata);  

        // Create the new schema 
        $tool->createSchema($metadata);

        $this->em = $em;
    }

    /**
     * @return EntityManager
     */
    public function getEntityManager()
    {
        return $this->em;
    }
}

用法:

public function setUp()
{   
    // Create the schema
    $db = new Db();
    $db->createSchema();

    // Enjoy
    $this->em = $db->getEntityManager();
}

希望这对你有所帮助。