我有一个基于Symfony 4的项目。我想开始基于WebTestCase
编写功能测试。我在配置中启用了framework.test: true
,并在phpunit中提供了APP_ENV=test
。
为测试环境构建的服务容器存在问题。我实际上并没有改变APP_ENV
和framework.test
的期望。
当我从测试缓存容器中获取服务时,我最终得到:
Maximum function nesting level of '256' reached, aborting!
在堆栈跟踪中,我可以看到symfony的DI一直试图获取相同的服务:
...
ContainerE6ODQnH\srcApp_KernelTestDebugContainer->getPanel_Model_EventService() at /var/www/html/panel/var/cache/test/ContainerE6ODQnH/srcApp_KernelTestDebugContainer.php:483
ContainerE6ODQnH\srcApp_KernelTestDebugContainer->getDefaultEventRepositoryService() at /var/www/html/panel/var/cache/test/ContainerE6ODQnH/srcApp_KernelTestDebugContainer.php:525
ContainerE6ODQnH\srcApp_KernelTestDebugContainer->getDbReachingEventTranslationProviderService() at /var/www/html/panel/var/cache/test/ContainerE6ODQnH/srcApp_KernelTestDebugContainer.php:509
ContainerE6ODQnH\srcApp_KernelTestDebugContainer->getCachingEventTranslationProviderService() at /var/www/html/panel/var/cache/test/ContainerE6ODQnH/srcApp_KernelTestDebugContainer.php:541
ContainerE6ODQnH\srcApp_KernelTestDebugContainer->getEventContextTakingTranslatorService() at /var/www/html/panel/var/cache/test/ContainerE6ODQnH/srcApp_KernelTestDebugContainer.php:402
ContainerE6ODQnH\srcApp_KernelTestDebugContainer->getModelConfiguratorService() at /var/www/html/panel/var/cache/test/ContainerE6ODQnH/srcApp_KernelTestDebugContainer.php:1089
ContainerE6ODQnH\srcApp_KernelTestDebugContainer->getPanel_Model_EventService() at /var/www/html/panel/var/cache/test/ContainerE6ODQnH/srcApp_KernelTestDebugContainer.php:483
ContainerE6ODQnH\srcApp_KernelTestDebugContainer->getDefaultEventRepositoryService() at /var/www/html/panel/var/cache/test/ContainerE6ODQnH/srcApp_KernelTestDebugContainer.php:525
ContainerE6ODQnH\srcApp_KernelTestDebugContainer->getDbReachingEventTranslationProviderService() at /var/www/html/panel/var/cache/test/ContainerE6ODQnH/srcApp_KernelTestDebugContainer.php:509
ContainerE6ODQnH\srcApp_KernelTestDebugContainer->getCachingEventTranslationProviderService() at /var/www/html/panel/var/cache/test/ContainerE6ODQnH/srcApp_KernelTestDebugContainer.php:541
ContainerE6ODQnH\srcApp_KernelTestDebugContainer->getEventContextTakingTranslatorService() at /var/www/html/panel/var/cache/test/ContainerE6ODQnH/srcApp_KernelTestDebugContainer.php:402
ContainerE6ODQnH\srcApp_KernelTestDebugContainer->getModelConfiguratorService() at /var/www/html/panel/var/cache/test/ContainerE6ODQnH/srcApp_KernelTestDebugContainer.php:1089
ContainerE6ODQnH\srcApp_KernelTestDebugContainer->getPanel_Model_EventService() at /var/www/html/panel/var/cache/test/ContainerE6ODQnH/srcApp_KernelTestDebugContainer.php:483
ContainerE6ODQnH\srcApp_KernelTestDebugContainer->getDefaultEventRepositoryService() at /var/www/html/panel/var/cache/test/ContainerE6ODQnH/srcApp_KernelTestDebugContainer.php:525
ContainerE6ODQnH\srcApp_KernelTestDebugContainer->getDbReachingEventTranslationProviderService() at /var/www/html/panel/var/cache/test/ContainerE6ODQnH/srcApp_KernelTestDebugContainer.php:509
ContainerE6ODQnH\srcApp_KernelTestDebugContainer->getCachingEventTranslationProviderService() at /var/www/html/panel/var/cache/test/ContainerE6ODQnH/srcApp_KernelTestDebugContainer.php:541
ContainerE6ODQnH\srcApp_KernelTestDebugContainer->getEventContextTakingTranslatorService() at /var/www/html/panel/var/cache/test/ContainerE6ODQnH/srcApp_KernelTestDebugContainer.php:402
ContainerE6ODQnH\srcApp_KernelTestDebugContainer->getModelConfiguratorService() at /var/www/html/panel/var/cache/test/ContainerE6ODQnH/srcApp_KernelTestDebugContainer.php:1089
ContainerE6ODQnH\srcApp_KernelTestDebugContainer->getPanel_Model_EventService() at /var/www/html/panel/var/cache/test/ContainerE6ODQnH/srcApp_KernelTestDebugContainer.php:483
...
这很奇怪,因为我的定义中没有循环引用。 在APP_ENV=dev
中一切正常。
由于某种原因,test
容器无法记住$this->services
属性中对现有服务的引用。
您知道开发容器和测试容器的构建差异是什么吗?
当我将测试容器的php文件与开发版本进行比较时。他们确实是不同的。没有理由...
更新
以下是在调用循环中生成的服务的示例:
DEV
protected function getDefaultEventRepositoryService()
{
$a = \ClassRegistry::init('Event');
$this->services['Panel\\Events\\Repository\\DefaultEventRepository'] = $instance = new \Panel\Events\Repository\DefaultEventRepository($a, ($this->services['Panel\\Events\\Repository\\EventMapper'] ?? ($this->services['Panel\\Events\\Repository\\EventMapper'] = new \Panel\Events\Repository\EventMapper())), ($this->privates['timeProvider'] ?? ($this->privates['timeProvider'] = new \Panel\Core\Utils\CurrentTimeProvider())));
($this->services['CakeFramework\\ModelConfigurator'] ?? $this->getModelConfiguratorService())->configure($a);
return $instance;
}
测试
protected function getDefaultEventRepositoryService()
{
$a = $this->getPanel_Model_EventService();
if (isset($this->services['Panel\\Events\\Repository\\DefaultEventRepository'])) {
return $this->services['Panel\\Events\\Repository\\DefaultEventRepository'];
}
return $this->services['Panel\\Events\\Repository\\DefaultEventRepository'] = new \Panel\Events\Repository\DefaultEventRepository($a, ($this->services['Panel\\Events\\Repository\\EventMapper'] ?? ($this->services['Panel\\Events\\Repository\\EventMapper'] = new \Panel\Events\Repository\EventMapper())), ($this->privates['timeProvider'] ?? ($this->privates['timeProvider'] = new \Panel\Core\Utils\CurrentTimeProvider())));
}
如您在上面看到的,有细微的差别。测试环境正在使用服务方法getPanel_Model_EventService
。但是在开发环境中,它是直接注入的$a = \ClassRegistry::init('Event');
这导致循环引用,尽管服务定义相同。没有其他service_test
文件。知道为什么吗?
答案 0 :(得分:0)
我调查了这个问题。这是由Symfony的配置器机制和缺乏报告循环依赖关系引起的。
我在公共仓库https://github.com/kamilwylegala/symfony-configurator-circular-dependency
中用代码示例描述了此问题。改用工厂有助于确定确实存在循环依赖。使用工厂加薪:
PHP Fatal error: Uncaught Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException: Circular reference detected for service ...