问题描述
我在Symfony 4项目中进行了单元测试,该单元测试显示出不一致的行为,并且我怀疑教义缓存是造成这种情况的原因。因此,我正在寻找一种禁用单元测试缓存的方法。
我当前用于环境测试的packages / test / doctrine.yaml文件如下:
doctrine:
orm:
auto_generate_proxy_classes: false
Metadata_cache_driver:
type: service
id: doctrine.system_cache_provider
query_cache_driver:
type: service
id: doctrine.system_cache_provider
result_cache_driver:
type: service
id: doctrine.result_cache_provider
services:
doctrine.result_cache_provider:
class: Symfony\Component\Cache\DoctrineProvider
public: false
arguments:
- '@doctrine.result_cache_pool'
doctrine.system_cache_provider:
class: Symfony\Component\Cache\DoctrineProvider
public: false
arguments:
- '@doctrine.system_cache_pool'
framework:
cache:
pools:
doctrine.result_cache_pool:
adapter: cache.app
doctrine.system_cache_pool:
adapter: cache.system
如果我想在测试中禁用任何缓存,是否有任何缓存驱动程序,这是非缓存虚拟对象?如果我将这些条目留空,则可能会使用我的产品设置或常规设置,这意味着结果也将被缓存。我可以明确地不缓存吗?我希望我不必写一个显式的伪缓存提供程序,谁不缓存?这可能是一个解决方案,但在我看来应该更容易实现。
config
\__packages
|
|__ prod
| \__doctrine.yaml
|
|__ dev
| \__doctrine.yaml
|
|__ test
| \__doctrine.yaml
|
\__doctrine.yaml
这是我扩展的KernelTestCase类:
protected EntityManagerInterface $em;
public static function setUpBeforeClass(): void
{
parent::setUpBeforeClass();
$kernel = static::createKernel();
$kernel->boot();
$em = $kernel
->getContainer()
->get('doctrine')
->getManager();
$schemaTool = new SchemaTool($em);
$Metadata = $em
->getMetadataFactory()
->getAllMetadata();
// Drop and recreate tables for all entities
$schemaTool->dropSchema($Metadata);
$schemaTool->createSchema($Metadata);
}
protected function setUp(): void
{
parent::setUp();
self::ensureKernelShutdown();
$kernel = static::createKernel();
$kernel->boot();
$this->em = $kernel
->getContainer()
->get('doctrine')
->getManager();
// loads tests data for every tests
$projectDir = $kernel->getProjectDir();
system('PHP ' . $projectDir . '/bin/console doctrine:fixtures:load --env=test -n -q');
}
....
protected function tearDown(): void
{
parent::tearDown();
if (null !== $this->em) {
$this->em->close();
}
}
解决方法
缓存配置
如果我将这些条目留空,则可能会使用我的产品设置或常规设置
否,产品中的设置永远不会在测试环境中使用。测试使用config/packages/test/
中的配置,并回退到config/packages/
中的常规设置,但从不进行生产。
在典型的设置中,诸如{mapping}的通用原则在config/packages/doctrine.yaml
中进行了定义,缓存仅在config/packages/prod/doctrine.yaml
中进行了定义。参见official symfony demo application
您还可以使用bin/console debug:config doctrine --env=test
验证配置。
测试隔离
您的问题很可能不是由教义缓存配置引起的,而是由于测试用例的隔离不良所致。
看看Functional Testing of A Doctrine Repository。 Symfonys官方文档建议在setUp()
处启动内核,并在tearDown()
期间关闭实体管理器。
如果对于您而言,完全隔离不是可行的方法,则必须进行调试以找出导致隔离破坏的测试用例。如果固定了引起问题的测试用例,则应检查其执行路径,并检查是否缺少丢失的规则刷新以及是否有比预期更长的事务。
,由于这里大家的建议,看来我终于解决了我的问题。现在至少有40条测试是绿色的。
我做了什么:
在为每个测试手动加载我的装置并尝试为每个测试类然后为每个测试重新创建数据库之前。 我完全将其丢弃,现在仅依靠Dama Bundle和事务回滚来获取未修改的测试数据。
dama_doctrine_test:
enable_static_connection: true
enable_static_meta_data_cache: false
enable_static_query_cache: false
在Dama Bundle的配置中,我确实将查询和元数据的缓存设置为false。我不确定这是否必要。但是由于它并没有降低我的测试速度,所以我保留了它。
这种组合终于成功了。
感谢@ domis86 @ simon.ro的支持和耐心!
https://symfony.com/doc/4.4/testing/database.html#resetting-the-database-automatically-before-each-test https://github.com/dmaicher/doctrine-test-bundle