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

9

26

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

Drink answered 28/8, 2017 at 15:20 Comment(1)
I am not sure you can override container variables at the application level? Maybe these help: github.com/docker/compose/issues/3183, philippe.bourgau.net/…Illation
D
15

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.

Drink answered 29/8, 2017 at 13:29 Comment(1)
Wrong answer. You can override it. Use force="true" attribute. <env name="APP_ENV" value="testing" force="true"/>Oly
A
22

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

Asquith answered 18/12, 2018 at 11:31 Comment(1)
@Drink this should be the chosen answer, so that you can still use those env params in your docker-compose fileDrat
D
15

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.

Drink answered 29/8, 2017 at 13:29 Comment(1)
Wrong answer. You can override it. Use force="true" attribute. <env name="APP_ENV" value="testing" force="true"/>Oly
E
5

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.

Elinoreeliot answered 28/8, 2017 at 19:8 Comment(6)
Thanks but none of your suggestion will work for me.Drink
Why not? Nobody can help if you don't give us the details.Illation
Added some details from discovery I found so far.Drink
using php artisan config:clear worked for me and allowed my tests to run against the testing database. Their should be a better way for testing to get it to always connect to the testing database and not overwrite the primary database without wiping out this config. When I rebooted the docker setup the config came back so I would need to do this every time I rebooted the containers.Toed
FYI: It would be config('app.env');. The config function uses dot notation. config('APP_ENV') will always be null.Bigoted
thank you for this inspiration!Plectrum
W
4

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!

Widgeon answered 6/6, 2019 at 17:26 Comment(1)
for my case i'm using laradock, so i delete my local bootstrap/cache the run the test and it workedInner
T
2

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

Tangleberry answered 4/10, 2019 at 3:1 Comment(0)
A
1

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.

Allenaallenby answered 13/10, 2021 at 14:30 Comment(0)
C
1

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';
   });
}
Catheterize answered 16/11, 2021 at 23:57 Comment(0)
I
0

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

Isonomy answered 19/1, 2022 at 1:18 Comment(0)
A
0

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" />
Abranchiate answered 15/3 at 19:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.