koalaok
koalaok

Reputation: 5760

Why phpunit is not getting the correct APP_ENV as specified in phpunit.xml?

I'm using Laravel and this is my ./phpunit.xml file

<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         bootstrap="bootstrap/autoload.php"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false">
    <testsuites>
        <testsuite name="FeatureTests">
            <directory suffix="Test.php">./tests/Feature</directory>
        </testsuite>

        <testsuite name="UnitTests">
            <directory suffix="Test.php">./tests/Unit</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist processUncoveredFilesFromWhitelist="true">
            <directory suffix=".php">./app</directory>
        </whitelist>
    </filter>
    <php>
        <env name="APP_ENV" value="testing"/>
        <env name="CACHE_DRIVER" value="array"/>
        <env name="SESSION_DRIVER" value="array"/>
        <env name="QUEUE_DRIVER" value="sync"/>
        <env name="DB_CONNECTION" value="sqlite_testing" />
    </php>
</phpunit>

I'm firing one of my test suites with the following command:

./vendor/phpunit/phpunit/phpunit --testsuite UnitTests

Inside my test method I have:

public function testAllMandatoryData()
{
   dump(env('APP_ENV'));
   ....
}

It's displaying "local" I was expecting "testing" as specified in phpunit.xml

         <env name="APP_ENV" value="testing"/>

Edit: additional details I have this laravel application running in a Docker container

On the docker-compose.yml I set some environment variables like:

environment:
  - APP_ENV=local
  - DB_HOST=192.168.0.22
  - DB_PORT=33306
  - DB_DATABASE=mydatabase
  - DB_USERNAME=homestead
  - DB_PASSWORD=homestead

What I've noticed is that directives in phpunit.xml like:

    <env name="APP_ENV" value="testing"/>

have no effect when the name is there in the docker-compose already.

Instead if I add some not defined in docker-compose.yml will be correctly set at phpunit runtime, like:

    <env name="DB_CONNECTION" value="sqlite_test"/>

end Edit

What I'm missing?

Thanks

Upvotes: 28

Views: 16020

Answers (9)

Joey Rich
Joey Rich

Reputation: 449

For me, changing "env" tags to "server" resolved this problem where variables set in phpunit.xml were not taking effect.

<server name="APP_ENV" value="testing" force="true" />

Upvotes: 1

mhmdomer
mhmdomer

Reputation: 93

For docker users, I added a new test script to composer.json file:

"test": [
        "DB_CONNECTION=sqlite && DB_DATABASE=:memory: && APP_ENV=testing && phpunit --colors=always --no-coverage"
        ],

This script is just overriding the environment variables defined in docker-compose.json

Upvotes: 0

Raza
Raza

Reputation: 3383

I had to resort to this little hack to get the environment to 'testing', I had to put this in TestCase.php

protected function setUp(): void
{
   parent::setUp();
   $this->app->detectEnvironment( function () {
      return 'testing';
   });
}

Upvotes: 1

Arif I.
Arif I.

Reputation: 2192

Try clearing your config cache by running the command php artisan config:clear. It is because you probably ran the command php artisan config:cache before running your tests and your APP_ENV was cached as local.

Upvotes: 1

Don&#39;t Panic
Don&#39;t Panic

Reputation: 14520

Use config('app.env') instead. env() values might be cached, in which case php artisan config:clear might help, though I've also had problems with accessing env values from command line environments.

More info here and here.

Upvotes: 5

Gilberto Albino
Gilberto Albino

Reputation: 2745

I run into the same problem when using Docker alongside docker-compose, and the fact was that my docker-compose.yml was loading Laravel's .env file. So, I solved it by creating a .env.docker file and setting (in docker-compose.yml):

  env_file:
    - .env.docker

It worked like a charm, and PHPUnit was able to select my .env.testing file insted of .env

Upvotes: 2

Sebastian Bruno
Sebastian Bruno

Reputation: 187

I had the same problem, .env variables seemed to be overriding the ones from my phpunit.xml, here are some of the solutions that could work:

  1. Specify which phpunit.xml file to use when running phpunit, it may be using a wrong one. vendor/bin/phpunit --configuration [path to your phpunit.xml]
  2. Clean the config cache. php artisan config:cache
  3. If you're in a Docker container, the above action may not work for you. What I did was to delete manually the bootstrap/cache files.

Hope it helps!

Upvotes: 4

pscheit
pscheit

Reputation: 2981

use

<env name="APP_ENV" value="testing" force="true"/>
<env name="CACHE_DRIVER" value="array" force="true"/>
<env name="SESSION_DRIVER" value="array" force="true"/>
<env name="QUEUE_DRIVER" value="sync" force="true"/>
<env name="DB_CONNECTION" value="sqlite_testing" force="true"/>

Without the force parameter, it won't work. See this issue: https://github.com/sebastianbergmann/phpunit/issues/2353 and the merged PR: https://github.com/sebastianbergmann/phpunit/pull/2723

Upvotes: 23

koalaok
koalaok

Reputation: 5760

I try to answer myself with the best option I found.

If you set ENV variables at docker-compose.yml file you won't be able to overwrite them with phpunit.xml directives such as:

  <env name="APP_ENV" value="testing"/>

Then you should opt for removing (like in this example) APP_ENV variable set from docker-compose.yml

And rely on .env Laravel file

APP_ENV=local

With this setup, phpunit will be able to overwrite the APP_ENV to "testing"

I'm still not 100% sure this arrangement is needed, with all docker agent versions. Another host I have with another Docker version behaves differently.

Upvotes: 16

Related Questions