运行 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

问题:

我假设在测试期间使用这些参数时,它们的值是abclive。但是,日志显示,ApiService 是在运行测试时使用默认值 nullsandbox 创建的。

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'

直接在浏览器中使用项目时,一切正常。

devprodtest 环境都使用相同的配置文件,没有特殊的 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()-&gt;getParameter('some_bundle.api.mode'))。如何使用.env.xxx 文件解决此问题? 很抱歉没有深入阅读整个问题。您是否正确注册了捆绑包以便使用所有环境? ['all' =&gt; true] 你也启动过内核吗? @James 是的,内核已启动(如问题中所述),并且捆绑包也使用['all' =&gt; 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 测试时出错

在更改时运行PHPUnit测试

Composer 自动加载器在运行测试时找不到 PHPUnit

在单独的进程中运行测试时,PHPUnit 无法生成代码覆盖率

Laravel / PHPUnit:运行测试时没有模拟类