使用数据库连接测试Symfony 3.4+捆绑包

时间:2020-07-22 20:17:52

标签: database testing bundle symfony-3.4

我正在尝试确定使用Travis进行连接以测试数据库的最佳配置方法。通常,在项目内部使用捆绑软件时,会将DB连接指定为项目配置的一部分(config / packages / doctrine.yaml)。但是,在使用CI测试时,捆绑软件将安装在测试项目的根目录中,而相关性将安装在/ vendor中。我仅需要出于测试目的而在捆绑软件中配置连接。

我想做的是使用SQLite内存数据库配置一个学说连接,在CI测试中创建模式,然后运行我的phpunit测试。如果捆绑软件安装在正常的Symfony项目中,则所有测试都可以正常运行。

尝试配置数据库让我非常沮丧。我已经在这里待了几天,试图追踪加载配置时发生了什么(不是)。

我在测试类中加载了一个内核,该内核扩展了KernelTestCase,如下所示:

class CommandSchedulerTest extends KernelTestCase
{
    /**
     * @var \Doctrine\ORM\EntityManagerInterface
     */
    private $entityManager;

    protected static function getKernelClass()
    {
        return TestKernel::class;
    }

    protected function setUp()
    {
        self::bootKernel();

        $this->entityManager = static::$kernel->getContainer()->get('doctrine')->getManager();
    }
...

还有我的内核类:

<?php

namespace Xact\CommandScheduler\Tests;

use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Routing\RouteCollectionBuilder;

class TestKernel extends Kernel
{
    use MicroKernelTrait;

    /**
     * @inheritDoc
     */
    public function registerBundles()
    {
        $bundles = [
            \Symfony\Bundle\FrameworkBundle\FrameworkBundle::class,
            \Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class,
            \Doctrine\Bundle\DoctrineCacheBundle\DoctrineCacheBundle::class,
            \Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class,
        ];

        foreach ($bundles as $class) {
            yield new $class();
        }
    }

    protected function configureRoutes(RouteCollectionBuilder $routes)
    {
        $confDir = $this->getProjectDir().'/Resources/config';
        $routes->import($confDir.'/routing.yaml');
    }

    protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
    {
        $confDir = $this->getProjectDir().'/Resources/config';
        $loader->load($confDir . '/test/doctrine.yaml');
        $loader->load($confDir . '/test/framework.yaml');
    }
}

我的doctrine.yaml文件供参考:

doctrine:
    dbal:
        url: "sqlite:///:memory:"

我设法破解了配置加载过程,并且可以看到我的framework.yaml文件的内容已添加到参数列表中。我也知道doctrine.yaml文件正在解析,因为如果我在根目录下添加'dbal'或'orm'以外的任何内容,则会出现错误。但是,我似乎没有在参数列表中找到连接。

我遇到这样的错误:

1) Xact\CommandScheduler\Tests\CommandSchedulerTest::testSet
InvalidArgumentException: Doctrine ORM Manager named "" does not exist.

/var/projects/command-scheduler/vendor/doctrine/persistence/lib/Doctrine/Persistence/AbstractManagerRegistry.php:151
/var/projects/command-scheduler/Tests/CommandSchedulerTest.php:25

这使我认为我的学说配置未正确加载。

我也尝试通过PrependExtensionInterface :: prepend添加配置,因为我已经读到有关在Kernel :: configureContainer期间加载数据库连接的建议为时已晚。但是,此操作无济于事,并出现了其他错误,表明已忽略内核中加载的任何配置文件。

我将非常感谢您提供一些帮助,以帮助我确定自己是否处在正确的轨道上,我是否正在尝试做一些无法完成的事情?我是否错过了设置中最基本的内容?我不知道。我所知道的是,我失去了多一点的头发,这令人不安!

1 个答案:

答案 0 :(得分:0)

好一会儿,我终于发现了我的错误。如果未在doctrine.yaml文件中指定“ orm”部分,则永远不会通过doctrine-bundle DoctrineExtension类加载ORM配置(请参见load()和ormLoad())。

已经将我的yaml文件更新为以下文件,我可以正常运行。我还添加了驱动程序参数,因为该参数默认为'pdo_mysql',它可能在内部得到修复,但是在调试连接参数列表时它看起来不对。

Resources / test / doctrine.yaml

doctrine:
    dbal:
        url: "sqlite:///:memory:"
        driver: 'pdo_sqlite'

    orm:
        auto_generate_proxy_classes: true
        naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
        auto_mapping: true
        mappings:
            XactCommandSchedulerBundle:
                is_bundle: false
                type: annotation
                dir: '%kernel.project_dir%/Entity'
                prefix: 'Xact\CommandScheduler\Entity'

我还必须将dotrine / orm添加到我的composer.json文件中。在我的完整Symfony应用程序中,该应用程序已由symfony / orm-pack元软件包插入。

...
    "require": {
        "php": "^7.0",
        "doctrine/doctrine-bundle": "~1.12",
        "doctrine/orm": "~2.5",
        "sensio/framework-extra-bundle": "~5.4",
        "symfony/monolog-bundle": "~3.5",
        "symfony/yaml": "^3.4.30",
    },
...

要完成图片以防其他人想要这样做,这是我设置中的其他文件。

Resources / config / test / framework.yaml

framework:
    secret: '78yb%$5JuI)7R'
    test: true
    session:
        storage_id: session.storage.mock_file

DependencyInjection / XactCommandSchedulerExtension.php

namespace Xact\CommandScheduler\DependencyInjection;

use Symfony\Component\Config\FileLocator;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Extension\Extension;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;

class XactCommandSchedulerExtension extends Extension
{
    public function load(array $configs, ContainerBuilder $container)
    {
        $loader = new YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
        $loader->load('services.yaml');
    }
}

Tests / TestKernel.php

<?php

namespace Xact\CommandScheduler\Tests;

use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\Config\Loader\LoaderInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpKernel\Kernel;
use Symfony\Component\Routing\RouteCollectionBuilder;

class TestKernel extends Kernel
{
    use MicroKernelTrait;

    /**
     * @inheritDoc
     */
    public function registerBundles()
    {
        $bundles = [
            \Symfony\Bundle\FrameworkBundle\FrameworkBundle::class,
            \Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class,
            \Doctrine\Bundle\DoctrineCacheBundle\DoctrineCacheBundle::class,
            \Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class,
        ];

        foreach ($bundles as $class) {
            yield new $class();
        }
    }

    protected function configureRoutes(RouteCollectionBuilder $routes)
    {
        $confDir = $this->getProjectDir().'/Resources/config';
        $routes->import($confDir.'/routing.yaml');
    }

    protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
    {
        $confDir = $this->getProjectDir().'/Resources/config';
        $loader->load($confDir . '/{test}/*' . '.yaml', 'glob');
    }
}

Tests / CommandSchedulerTest.php

<?php

namespace Xact\CommandScheduler\Tests;

use Doctrine\ORM\Tools\SchemaTool;
use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase;
use Xact\CommandScheduler\Entity\ScheduledCommand;
use Xact\CommandScheduler\Scheduler\CommandScheduler;

class CommandSchedulerTest extends KernelTestCase
{
    /**
     * @var \Doctrine\ORM\EntityManagerInterface
     */
    private $entityManager;

    protected static function getKernelClass()
    {
        return TestKernel::class;
    }

    /**
     * @inheritDoc
     */
    protected function setUp(): void
    {
        self::bootKernel();

        $this->entityManager = static::$kernel->getContainer()->get('doctrine')->getManager();
        
        $schemaTool = new SchemaTool($this->entityManager);
        $metadata = $this->entityManager->getMetadataFactory()->getAllMetadata();
        $schemaTool->createSchema($metadata);
    }

    /**
     * @inheritDoc
     */
    protected function tearDown(): void
    {
        $this->entityManager->close();
        $this->entityManager = null;
    }

....