Laravel testing and config hierarchy

2 min read

Laravel testing and config hierarchy

I recently had to upgrade an older legacy Laravel system to bring it up to date. When I do these upgrades, I’ll generally follow the instructions on the Laravel upgrade pages, and then I’ll go through the git diff between the versions, and update my system to be as accurate to a brand new Laravel install as possible. You don’t need to do this, this is just my personal preference.

One of the changes that I needed to do was update the phpunit.xml file so that instead of using the <server> element, we now use the <env> element. This had a strange effect of now causing a lot of the automated tests to now fail.

Switching back to <server> would fix it. Comparing the values in the projects .env.testing file I noticed that there were some differences, changing the items in the phpunit.xml file to those in the .env.testing file would fail again.

After investigating the priority order is:

PrioritySourceOverwrites?
Highestconfig()->set('key', 'value');Yes, everything at run time
Highphpunit.xml <server>Overwrites <env>, .env and .env.* files
Mediumphpunit.xml <env>Overwrites .env and .env.* files
Low.env.*Overwrites default .env file
Lowest.envDefault

Now why does this matter? Setting a <server> variable will update the PHP $_SERVER superglobal value, and likewise setting a <env> will update the PHP $_ENV superglobal value. Both of these will overwrite your .env variables, so who cares?

The issue comes when you have multiple different environment files. You’ve got your local testing file, .env.testing and your continuous integration one .env.ci, and maybe you have some more. If any of these files need a different value for the same key, then the custom .env.* file would only update an <env> variable, and not the <server> ones!

And let’s not forget about config()->set('key', 'value') this will take priority over any of the others, allowing you to test multiple different scenarios in your automated tests.