我正在尝试确定使用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期间加载数据库连接的建议为时已晚。但是,此操作无济于事,并出现了其他错误,表明已忽略内核中加载的任何配置文件。
我将非常感谢您提供一些帮助,以帮助我确定自己是否处在正确的轨道上,我是否正在尝试做一些无法完成的事情?我是否错过了设置中最基本的内容?我不知道。我所知道的是,我失去了多一点的头发,这令人不安!
答案 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;
}
....