运行 PHPUnit 测试时,容器参数在 Symfony 5 服务中不可用/注入
Posted
技术标签:
【中文标题】运行 PHPUnit 测试时,容器参数在 Symfony 5 服务中不可用/注入【英文标题】:Container parameter not available/injected in Symfony 5 service when runnig PHPUnit tests 【发布时间】:2021-12-30 01:40:19 【问题描述】:在为我的 Symfony 5 项目创建一些(功能性)phpUnit 测试时,我遇到了一个问题,即容器参数在测试期间没有正确地注入到服务中:
例如,项目中可以使用以下参数:
// config/packages/some_bundle.yaml
some_bundle:
api:
key: 'abc' // default value is null
mode: 'live' // default value is 'sandbox'
// SomeBundle/config/services.yaml
services:
_defaults:
autowire: true
autoconfigure: true
bind:
$apiMode: '%some_bundle.api.mode%'
$apiKey: '%some_bundle.api.key%'
// SomeBundle/src/Service/ApiService.php
class ApiService
public function __construct($apiMode, $apiKey)
// log mode and key ...
// Checking that parameters are available
$ php bin/console debug:container --parameters --env=test
Symfony Container Parameters
============================
-------------------------------------------
Parameter Value
-------------------------------------------
...
some_bundle.api.key abc
some_bundle.api.mode live
问题:
我假设在测试期间使用这些参数时,它们的值是abc
和live
。但是,日志显示,ApiService
是在运行测试时使用默认值 null
和 sandbox
创建的。
testCase 扩展KernelTestCase
并且内核被引导。直接从测试容器中获取参数也显示错误值:
// Within the test case
$mode = self::getContainer()->getParameter('some_bundle.api.mode');
$this->assertEquals($mode, 'live', 'error');
// test output
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'live'
+'sandbox'
直接在浏览器中使用项目时,一切正常。
dev
、prod
和 test
环境都使用相同的配置文件,没有特殊的 env.test
文件。
phpunit.xml.dist
文件设置为使用test
环境,但此处使用其他环境没有任何区别。
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ...>
<php>
<server name="APP_ENV" value="test" force="true" />
...
如何解决这个问题?运行测试时是否完全跳过容器参数并且只能使用默认值?还是我的配置有问题?
【问题讨论】:
env.local 变量未在测试中加载。您必须使用您的测试配置创建一个 env.test 或 env.test.local 文件,或者将变量添加到 phpunit.xml.dist 我不确定这是否相关,因为这是关于容器参数,而不是环境变量。我必须在env.test
中包含什么才能使自动装配正确地注入容器参数some_bundle.api.mode
?如前所述,在终端中调用php bin/console debug:container --parameters --env=test
时,所有容器参数都显示为正确的测试值,但在测试期间访问时显示为默认值(例如,使用self::getContainer()->getParameter('some_bundle.api.mode')
)。如何使用.env.xxx
文件解决此问题?
很抱歉没有深入阅读整个问题。您是否正确注册了捆绑包以便使用所有环境? ['all' => true]
你也启动过内核吗?
@James 是的,内核已启动(如问题中所述),并且捆绑包也使用['all' => true]
在bundles.php
中正确注册
【参考方案1】:
我真的看不出你的做法有什么问题,并且认为它会起作用,尽管我不会注入这样的参数。在 DependencyInjection 文件夹中的包中,我将传递扩展文件中的参数,而不是将它们绑定到 services.yaml 中。
public function load(array $configs, ContainerBuilder $container): void
$loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config'));
$loader->load('services.yaml');
$definition = $container->getDefinition('SomeBundle/src/Service/ApiService');
$definition->addArgument($configs['api']['mode']);
$definition->addArgument($configs['api']['key']);
【讨论】:
以上是关于运行 PHPUnit 测试时,容器参数在 Symfony 5 服务中不可用/注入的主要内容,如果未能解决你的问题,请参考以下文章
仅当访问 Laravel 5 中的根页面( visit('/') )时,PHPUnit 测试才会失败
在 Laravel 8 中运行多个 PHPUnit 测试时出错
Composer 自动加载器在运行测试时找不到 PHPUnit