DEV Community

Davide de Paolis
Davide de Paolis

Posted on • Edited on

Testing against different Environment Variables and Deployment stages

One reason why I really like writing unit tests with AVA is that each test file is run in a separate Node.js process, therefore changes to global variables ( they should be avoided as much as possible anyway.. but that's another story) do not affect other tests.

By default, AVA will set process.env.NODE_ENV to test, therefore, it will search for a .env file in your project folder in order to populate all your Environment global variables (those that you access via process.env.MY_VARIABLE).

It might happen that you want to use different env files ( in our recent case we had a couple of integration tests and we wanted to make sure they were working on staging - and on the other hand by no means on production DB ).
Or that you want to test against a file with missing or broken or invalid values.

If you want to test with AVA against files different from .env.test then you can use dotenv to load your specific file into your test file.

import test from 'ava';
require('dotenv').config()

test('make sure env variables are loaded', t => {
    console.log(process.env.DB_HOST);
    console.log(process.env.DB_USER);
    t.truthy(process.env.DB_HOST);
});
Enter fullscreen mode Exit fullscreen mode

Since in our project we use Serverless framework and we rely on YAML files for our env variables we used a similar package, env-yaml whose usage is pretty identical:

require('env-yaml').config({path: path.resolve('./envs/env.dev.yml')})
test('make sure env variables are loaded', t => {
    console.log(process.env.DB_HOST);
    t.truthy(process.env.DB_HOST);
});
Enter fullscreen mode Exit fullscreen mode

By importing directly the files you need in every test file, since every test file runs in its node process, you can use different env files in different tests or test against variables in different environments or again test against missing variables without having to worry about messing global configs and therefore having to reset everything during tear-down phase.

Assuming you have an envs folder with different environment-variables files named after your environment/deployment-stage and each file contains

DB_NAME: 'current_env_db'
DB_USER: 'current_env_user'
Enter fullscreen mode Exit fullscreen mode

you can run different tests ( from different files) and be sure you have different env globals set on the process.

inside env-vars-production.test.js

test("staging variables are loaded", t => {
  require('env-yaml').config({path: path.resolve('./envs/env.staging.yml')})
    t.is(process.env.DB_NAME, 'staging_db');
})
Enter fullscreen mode Exit fullscreen mode

inside env-vars-development.test.js

test("development variables are loaded", t => {
    require('env-yaml').config({path: path.resolve('./envs/env.dev.yml')})
    t.is(process.env.DB_NAME, 'dev_db');
})
Enter fullscreen mode Exit fullscreen mode

inside env-vars-missing.test.js

test('ops we forgot to load env variables', t=> {
    t.falsy(process.env.DB_NAME);
})
Enter fullscreen mode Exit fullscreen mode

Of course I am not suggesting having unit test to make sure all your variables are there and are of a specific value, I just wanted to show how you can run test with different env files and unit-test those bits of your code that might rely on specific global variables or might break in case those values are not set.

Hope this helps :-)

Top comments (0)