首页 > 解决方案 > Symfony 4.1 功能测试中的环境变量/隔离环境变量

问题描述

我的用例是以下场景: https ://symfony.com/doc/current/testing/insulating_clients.html

createClient() 为每次调用创建一个新内核。它重新启动内核(在请求之间)。

现在使用 symfony4 中的新环境变量系统,我遇到了问题。我的内核取决于环境参数“租户”。由于 symfony 4.x 中环境变量的性质,每次启动内核时都会读取 env 变量。

因此,当我连续创建新内核时,env 变量将在(重新)引导时更改其值。

我将如何冻结内核中的环境变量?或者我将如何覆盖从“env”读取 env 变量的机制。例如,我想准备内核,以便配置中的 env 变量不是从真实环境中读取,而是从保存在内核实例中的数组中读取,等等。

覆盖 \Symfony\Component\DependencyInjection\EnvVarProcessor 似乎是一个好技巧,但是这个服务是在容器编译时创建和缓存的,我将在哪里注入我的绝缘 env 参数?

$client->insulate() 也不起作用(我不想使用它)

标签: symfonytestingsymfony4

解决方案


正如@Nikita Leshchev 在评论中提到的那样,您必须在调用之前设置环境变量createClient()。为了在当前测试中“密封”环境变量,以便您的更改不会影响其他测试,您必须将其设置回测试完成时的状态。

您可以使用putenv(),$_ENV$_SERVER设置和重置环境变量,但我不建议putenv()您这样做,因为您必须处理类型转换并且如果未定义变量:

public function testWithPutenv(): void
{
    // Save what the env is currently
    // You probably want to manually cast it to the type you need
    // This will return false if the env var is not set
    // which can't really be handled very well
    $originalEnv = getenv('MY_ENV_VAR');

    // Set the env to what you need
    putenv('MY_ENV_VAR=foo');

    $client = static::createClient();
    $client->request('POST', '/do-something');

    // assertions...

    // reset the env to what it was before
    putenv(sprintf('MY_ENV_VAR=%s', (string) $originalEnv));
}

public function testWithENV(): void
{
    // Save what the env is currently
    // Have a default if it's not set
    // Alternatively you can check whether it's set or not and 
    // use `unset` to "reset" it at the end of the test
    $originalEnv = $_ENV('MY_ENV_VAR') ?? 'bar';

    // Set the env to what you need
    $_ENV['MY_ENV_VAR'] = 'foo';

    $client = static::createClient();
    $client->request('POST', '/do-something');

    // assertions...

    // reset the env to what it was before
    $_ENV['MY_ENV_VAR'] = $originalEnv;
}

public function testWithENV(): void
{
    // Save what the env is currently
    // Default to empty string, so we know whether we need to unset it
    $originalEnv = $_SERVER('MY_ENV_VAR') ?? '';

    // Set the env to what you need
    $_SERVER['MY_ENV_VAR'] = 'foo';

    $client = static::createClient();
    $client->request('POST', '/do-something');

    // assertions...

    // reset the env to what it was before
    if ('' === $originalEnv) {
        unset($_SERVER['MY_ENV_VAR']);
    } else {
        $_SERVER['MY_ENV_VAR'] = $originalEnv;
    }
}

推荐阅读