Testing against different Environment Variables and Deployment stages
Tags: serverless, javascript, testing, node
Published: 2019-02-26 07:58:51

---
title: Testing against different Environment Variables and Deployment stages
published: true
description: simple tips on how to use environment files in unit and integration tests.
tags: #serverless, #javascript, #testing, #node
---

One reason why I really like writing unit tests with [AVA](https://github.com/avajs/ava) is that [each test file is run in a separate Node.js process](https://github.com/avajs/ava/blob/master/docs/01-writing-tests.md#process-isolation), 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](https://www.npmjs.com/package/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);
});
```

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](https://www.npmjs.com/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);
});
```

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'
```
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');
})
```
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');
})
```
inside env-vars-missing.test.js
```
test('ops we forgot to load env variables', t=> {
    t.falsy(process.env.DB_NAME);
})
```

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 :-)