How to stub process.env in node.js?

node.jsStubSinon

node.js Problem Overview


I want to stub process.env.FOO with bar.

var sinon = require('sinon');
var stub = sinon.stub(process.env, 'FOO', 'bar');

I'm confused. I read document, but still I don't understand yet.sinonjs docs

sinonjs is one example, not sinonjs is okay.

node.js Solutions


Solution 1 - node.js

From my understanding of process.env, you can simply treat it like any other variable when setting its properties. Keep in mind, though, that every value in process.env must be a string. So, if you need a particular value in your test:

   it('does something interesting', () => {
      process.env.NODE_ENV = 'test';
      // ...
   });

To avoid leaking state into other tests, be sure to reset the variable to its original value or delete it altogether:

   afterEach(() => {
       delete process.env.NODE_ENV;
   });

Solution 2 - node.js

I was able to get process.env to be stubed properly in my unit tests by cloning it and in a teardown method restoring it.

Example using Mocha

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

after(() => {
    process.env = env;
});

...

it('my test', ()=> {
    process.env.NODE_ENV = 'blah'
})

Keep in mind this will only work if the process.env is only being read in the function you are testing. For example if the code that you are testing reads the variable and uses it in a closure it will not work. You probably invalidate the cached require to test that properly.

For example the following won't have the env stubbed:

const nodeEnv = process.env.NODE_ENV;

const fnToTest = () => {
   nodeEnv ...
}

Solution 3 - node.js

With sinon you can stub any variable like this.

 const myObj = {
    example: 'oldValue', 
 };

 sinon.stub(myObj, 'example').value('newValue');

 myObj.example; // 'newValue'

This example is form sinon documentation. https://sinonjs.org/releases/v6.1.5/stubs/


With that knowledge, you can stub any environment variable. In your case it would look like this:

 let stub = sinon.stub(process.env, 'FOO').value('bar');

Solution 4 - node.js

How to quickly mock process.env during unit testing.

https://glebbahmutov.com/blog/mocking-process-env/

const sinon = require('sinon')
let sandbox = sinon.createSandbox()

beforeEach(() => {
  sandbox.stub(process.env, 'USER').value('test-user')
})

it('has expected user', () => {
  assert(process.env.USER === 'test-user', 'wrong user')
})

afterEach(() => {
  sandbox.restore()
})

But what about properties that might not exist in process.env before the test? You can use the following package and then you will be able to test the not exist env variables.

https://github.com/bahmutov/mocked-env

Solution 5 - node.js

In a spec-helper.coffee or something similar where you set up your sinon sandbox, keep track of the original process.env and restore it after each test, so you don't leak between tests and don't have to remember to reset every time.

_ = require 'lodash'
sinon = require 'sinon'

beforeEach ->
    @originalProcessEnv = _.cloneDeep process.env

afterEach ->
    process.env = _.cloneDeep @originalProcessEnv

In your test, use process.env as normal.

it 'does something based on an env var', ->
    process.env.FOO = 'bar'

Solution 6 - node.js

You can use this if you want to stub a key which not present in process.env

const sinon = require('sinon')
let sandbox = sinon.createSandbox();
sandbox.stub(process, 'env').value({ 'SOME_KEY': 'SOME_VALUE' });

Solution 7 - node.js

Like many others have pointed out the sinon way works unless you have the environment variables set before the test begins, e.g. in the file you are testing like so:

const foo = process.env.YOUR_VAR;

Gleb Bahmutov wrote an npm package that gives a nice way of setting environment variables in your tests no matter how you are referencing the environment variables.

Link to his page: https://glebbahmutov.com/blog/mocking-process-env/

Link to npm package: https://github.com/bahmutov/mocked-env

It worked great and was super easy to implement.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMatt - sanematView Question on Stackoverflow
Solution 1 - node.jsJoshua DuttonView Answer on Stackoverflow
Solution 2 - node.jsplleeView Answer on Stackoverflow
Solution 3 - node.jsGetriaxView Answer on Stackoverflow
Solution 4 - node.jsHossein RabizadehView Answer on Stackoverflow
Solution 5 - node.jsAndrew HomeyerView Answer on Stackoverflow
Solution 6 - node.jsMayank ChaurasiaView Answer on Stackoverflow
Solution 7 - node.jshanchan07View Answer on Stackoverflow