domanskyi
domanskyi

Reputation: 753

Test process.env value with JEST

I have config file with next if cases:

if (!process.env.NODE_ENV) {
  throw Error('Process environment is required!')
}

const allowedEnvironments = ['local', 'development', 'production']

if (!allowedEnvironments.includes(process.env.NODE_ENV)) {
  throw Error('Process environment not allowed! Choose another!')
}

How I can write tests for it? I have tried variant from here. But the test does not start with error 'Process environment not allowed! Choose another!'

Upvotes: 0

Views: 807

Answers (2)

Maxim Pyshko
Maxim Pyshko

Reputation: 580

1) You should better encapsulate your checks:

const allowedEnvironments = ['local', 'development', 'production'];

class AppEnv {
  constructor(env) {
    if (!env) {
      throw Error('Process environment is required!');
    }
    if (!allowedEnvironments.includes(env)) {
      throw Error('Process environment not allowed! Choose another!');
    }

    this._env = env;
  }

  get isLocal() {
    return this._env === 'local';
  }

  get isDevelopment() {
    return this._env === 'development';
  }

  get isProduction() {
    return this._env === 'production';
  }
}

export { AppEnv };

2) Then you could write tests for it without process.env:

import { AppEnv } from './app-env';

describe('AppEnv', () => {
  const createAppEnv = (env: string) => new AppEnv(env);

  it('should throw for empty env', () => {
    expect(() => createAppEnv('')).toThrow();
  });
  it('should throw for bad env', () => {
    expect(() => createAppEnv('_bad_env_value_')).toThrow();
  });
  it('should be local', () => {
    expect(createAppEnv('local').isLocal).toBe(true);
  });
  it('should be development', () => {
    expect(createAppEnv('development').isDevelopment).toBe(true);
  });
  it('should be production', () => {
    expect(createAppEnv('production').isProduction).toBe(true);
  });
});

3) In your config.js instantiate the AppEnv with process.env.NODE_ENV:

import { AppEnv } from './app-env';

const appEnv = new AppEnv(process.env.NODE_ENV);

export { appEnv };

4) Use the appEnv everywhere in your application:

import { appEnv } from './config';

if (appEnv.isDevelopment) {
  // do something
}

Upvotes: 0

Lin Du
Lin Du

Reputation: 102237

Here is the solution:

index.ts:

function checkEnvironmentVars() {
  if (!process.env.NODE_ENV) {
    throw Error('Process environment is required!');
  }

  const allowedEnvironments = ['local', 'development', 'production'];

  if (!allowedEnvironments.includes(process.env.NODE_ENV)) {
    throw Error('Process environment not allowed! Choose another!');
  }
}

export { checkEnvironmentVars };

Unit test:

import { checkEnvironmentVars } from './';

const originalEnv = Object.assign({}, process.env);

describe('checkEnvironmentVars', () => {
  it('should throw error when NODE_ENV is not set', () => {
    delete process.env.NODE_ENV;
    expect(() => checkEnvironmentVars()).toThrowError(Error('Process environment is required!'));
  });

  it('should throw error when NODE_ENV is invalid', () => {
    process.env.NODE_ENV = 'stage';
    expect(() => checkEnvironmentVars()).toThrowError(Error('Process environment not allowed! Choose another!'));
  });

  it('should pass the check', () => {
    process.env.NODE_ENV = 'local';
    expect(() => checkEnvironmentVars()).not.toThrow();
  });
});

Unit test result with coverage report:

 PASS  src/stackoverflow/56546760/index.spec.ts
  checkEnvironmentVars
    ✓ should throw error when NODE_ENV is not set (8ms)
    ✓ should throw error when NODE_ENV is invalid (2ms)
    ✓ should pass the check

----------|----------|----------|----------|----------|-------------------|
File      |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files |      100 |      100 |      100 |      100 |                   |
 index.ts |      100 |      100 |      100 |      100 |                   |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       3 passed, 3 total
Snapshots:   0 total
Time:        3.651s

Upvotes: 1

Related Questions