Environment specific variables in Laravel's testing environment

In Laravel, it's easy to set environment variables that are specific to your testing environment. Just edit your phpunit.xml file and set them as entries in the <php> block:

    <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_DATABASE" value=":memory:"/>
        <env name="DB_CONNECTION" value="sqlite"/>
        <env name="TWILIO_FROM_NUMBER" value="+15005550006"/>
    </php>

But what if you find yourself needing to exclude these values from version control?

My example #

I'm getting back to work on PulledOver, which uses Twilio as its foundation. I wanted to write some tests for my TwilioClient class, which directly connects to Twilio's API, so I was using Twilio's Test Credentials to send fake calls to the API and examine their responses.

But that means I have a Twilio SID and Token that I'm not supposed to expose to the public, right? I even asked around on Twitter:

I got quite a few responses, and one from the CEO of Twilio (!):

OK, so I need to exclude them. But how? I scratched my head a few times, dropped a question in the company Slack, and went to sleep. I woke up this morning and the ever-resourceful Keith Damiani had an answer for me: use Dotenv (which Laravel uses to load .env) to load a .env.test file in Laravel's TestCase base class. DUH. Here's how you do it:

Implementing .env.test in Laravel #

First, create a .env.test.example file and fill it with placeholders for whichever keys you want:

TWILIO_ACCOUNT_SID=fillmein
TWILIO_ACCOUNT_TOKEN=fillmein

Next, copy .env.test.example to .env.test and fill in the actual values.

Add .env.test to your .gitignore file.

Finally, add these line to tests/TestCase.php's createApplication method, just below $app = require __DIR__.'/../bootstrap/app.php';:

Note: Dotenv has changed their syntax recently, so I'll show two different versions here:

// Old Dotenv
if (file_exists(dirname(__DIR__) . '/.env.test')) {
    Dotenv::load(dirname(__DIR__), '.env.test');
}

// New Dotenv
if (file_exists(dirname(__DIR__) . '/.env.test')) {
    (new \Dotenv\Dotenv(dirname(__DIR__), '.env.test'))->load();
}

That's it! Your .env.test environment variables are now pulled into any test you run that extends TestCase, but those values are safely kept out of version control.


Comments? I'm @stauffermatt on Twitter


Tags: testing | laravel | dotenv

Matt Stauffer headshot

Hi, I'm Matt Stauffer.

I'm partner & technical director at Tighten Co.

You can find me on Twitter at @stauffermatt


Like what you're reading?

I wrote an entire 450+ page book for O'Reilly: Laravel: Up and Running.

You can order the eBook or print book today.