4

I face a problem with env variables and running tests with phpunit on symfony 4.2 framework.

According to the documentation, .env and services.yaml are loaded first but if the APP_ENV is defined and set to a value like test, the container will be configured to load .env.test and services_test.yaml.

What I want to understand is : my .env files contains a key APP_ENV set to dev, but when I run phpunit to execute some tests, the environment is automatically (?) set to test...

To see that, I've dump $this->environment in the class Kernel.php.

bootstrap.php

<?php

use Symfony\Component\Dotenv\Dotenv;
require dirname(__DIR__).'/vendor/autoload.php';
// Load cached env vars if the .env.local.php file exists
// Run "composer dump-env prod" to create it (requires symfony/flex >=1.2)
if (is_array($env = @include dirname(__DIR__).'/.env.local.php')) {
    $_SERVER += $env;
    $_ENV += $env;
} elseif (!class_exists(Dotenv::class)) {
    throw new RuntimeException('Please run "composer require symfony/dotenv" to load the ".env" files configuring the application.');
} else {
    // load all the .env files
    (new Dotenv())->loadEnv(dirname(__DIR__).'/.env');
}
$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) ?: 'dev';
$_SERVER['APP_DEBUG'] = $_SERVER['APP_DEBUG'] ?? $_ENV['APP_DEBUG'] ?? 'prod' !== $_SERVER['APP_ENV'];
$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int) $_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'], FILTER_VALIDATE_BOOLEAN) ? '1' : '0';

.env

###> symfony/framework-bundle ###
APP_ENV=dev
...

Kernel.php

protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader)
    {
        $container->addResource(new FileResource($this->getProjectDir().'/config/bundles.php'));
        // Feel free to remove the "container.autowiring.strict_mode" parameter
        // if you are using symfony/dependency-injection 4.0+ as it's the default behavior
        $container->setParameter('container.autowiring.strict_mode', true);
        $container->setParameter('container.dumper.inline_class_loader', true);
        $confDir = $this->getProjectDir().'/config';

        $loader->load($confDir.'/{packages}/*'.self::CONFIG_EXTS, 'glob');
        $loader->load($confDir.'/{packages}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, 'glob');
        $loader->load($confDir.'/{services}'.self::CONFIG_EXTS, 'glob');
        $loader->load($confDir.'/{services}_'.$this->environment.self::CONFIG_EXTS, 'glob');

        dump($this->environment); //print "test"
    }

phpunit.xml.dist

<?xml version="1.0" encoding="UTF-8"?>

<!-- https://phpunit.de/manual/current/en/appendixes.configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.8/phpunit.xsd"
         backupGlobals="false"
         colors="true"
         bootstrap="config/bootstrap.php"
>
    <php>
        <ini name="error_reporting" value="-1" />
        <server name="KERNEL_CLASS" value="AppBundle\Kernel" />

        <!-- ###+ symfony/framework-bundle ### -->
        <env name="APP_ENV" value="dev" force="true"/> <!-- doesn't work with or without force="true" -->

        <!-- env name="TRUSTED_PROXIES" value="127.0.0.1,127.0.0.2" -->
        <!-- env name="TRUSTED_HOSTS" value="'^localhost|example\.com$'" -->
        <!-- ###- symfony/framework-bundle ### -->

        <!-- ###+ doctrine/doctrine-bundle ### -->
        <!-- Format described at http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url -->
        <!-- For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data.db" -->
        <!-- Configure your db driver and server_version in config/packages/doctrine.yaml -->
        <env name="DATABASE_URL" value="sqlite:///%kernel.project_dir%/app/test.db"/>
        <!-- ###- doctrine/doctrine-bundle ### -->

    </php>

    <testsuites>
        <testsuite name="Project Test Suite">
            <directory>tests</directory>
        </testsuite>
    </testsuites>

    <filter>
        <whitelist>
            <directory>src</directory>
            <exclude>
                <directory>src/*Bundle/Resources</directory>
                <directory>src/*/*Bundle/Resources</directory>
                <directory>src/*/Bundle/*Bundle/Resources</directory>
            </exclude>
        </whitelist>
    </filter>
</phpunit>

Could you give me a clue about what happens, why my container is configure in test environment instead of the value of the APP_ENV?

Dralucas
  • 229
  • 2
  • 6
  • How exactly are you running your tests? Is there maybe something set in your `phpunit.xml`? – Nico Haase Feb 01 '19 at 15:19
  • 1
    I execute the command `phpunit` to run tests written in the `/tests` folder. My `phpunit.xml.dist` is pretty basic (I will edit my original post) – Dralucas Feb 01 '19 at 15:25
  • kind of have to ask.. why are you not mocking the container anyway? – DevDonkey Feb 01 '19 at 15:51
  • 1
    You are wondering why your environment is "test" when you run tests? Correct? – Calamity Jane Feb 01 '19 at 16:03
  • 1
    Yes ! I understand that it can be weird, but I just want to know where the environment is set to test when we run phpunit command. For me, it's counterintuitive to set APP_ENV to a specific value like dev and see the container built in test environment. – Dralucas Feb 01 '19 at 20:34
  • did you try to debug somewhere at https://github.com/symfony/framework-bundle/blob/3c06f4cd2351e735c2784ea2c1be7bea57c80217/Test/KernelTestCase.php#L85 (I mean you can find this file in your `vendor/symfony/...` directory and see what happens there) – xmike Feb 02 '19 at 10:28

0 Answers0