2

i have the following code in a file that i'm trying to test:

foo.js

let localEnv = (process.env.LOCAL_ENVIRONMENT).toLowerCase() === 'prod' ? 'prod' : 'stage';

currently, i set this value using setupFiles which points to env.js and it contains:

process.env.LOCAL_ENVIRONMENT = 'prod';

my question is, how do i change process.env.LOCAL_ENVIRONMENT to test (or anything else) in foo.test.js? Just need to do this in a single test, so this line will be covered in my test coverage.

I tried doing something like this but it didn't work...

foo.test.js

test('Nonprod', async () => { 
  process.env.LOCAL_ENVIRONMENT = 'test';
  ...
});
CoryDorning
  • 1,854
  • 4
  • 25
  • 36

3 Answers3

2

You can alter the value as you tried. However you have to take into account that in your original file you only access the variable when you first load this script. In order to make this work you have to do sth like this:

// in your test file foo.test.js
const prev = process.env.LOCAL_ENVIRONMENT
process.env.LOCAL_ENVIRONMENT = 'test'; // from now on the env var is test
const myModule = require('./foo.js'); // foo.js is executed and the var is read as test
process.env.LOCAL_ENVIRONMENT = prev; // change value back

This has some caveheats as you cant test multiple scenarios with this (as the module is only loaded in once).

If you want to test more scenarios you have multiple options:

One would be to split the logic and process.env.LOCAL_ENVIRONMENT apart, for example

function getLocalEnv(env = process.env.LOCAL_ENVIRONMENT) {
  return env.toLowerCase() === 'prod' ? 'prod' : 'stage';
}

This function is now very easy to test and doesn't depend on env vars for that anymore

Johannes Merz
  • 3,252
  • 17
  • 33
  • Hmm...not sure i entirely follow. What do you mean by original file in the comment "However you have to take into account that in your original file..." – CoryDorning Feb 10 '22 at 16:43
  • seems odd there isn't an elegant way to change an environment variable for just a single test... – CoryDorning Feb 10 '22 at 16:45
  • sorry, original file i mean `foo.js`. As this file is required it gets executed once, so your localDev gets computed exactly once and with the value process.env. LOCAL_ENVIRONMENT has at the time – Johannes Merz Feb 11 '22 at 11:31
  • gotcha. that makes sense now. can you further explain the `multiple` options you mentioned and how i might use it instead? – CoryDorning Feb 15 '22 at 14:55
  • ah, found the answer here, thanks for the assist: https://stackoverflow.com/questions/48989643/how-to-reset-module-imported-between-tests – CoryDorning Feb 15 '22 at 15:25
0

I found the answer on how to reset and re-require the tested module here: how to reset module imported between tests

CoryDorning
  • 1,854
  • 4
  • 25
  • 36
-1

The most easier way to test it for a specific test case is to set the test into a describe scope and to apply / remove the env value in beforeAll / afterAll or beforeEach / afterEach hooks depending on your needs.

describe('Test example', () => {
  describe('prod (default)', () => {
    test('do the thing', () => {
      doTheThing(); // process.env.LOCAL_ENVIRONMENT is by default 'prod' because of your setupFiles
    });
  });
  describe('test env', () => {
    const oldEnv = process.env.LOCAL_ENVIRONMENT; // or { ...process.env } to copy the whole env

    beforeAll(() => {
      process.env.LOCAL_ENVIRONMENT = 'test';
    });
    afterAll(() => {
      process.env.LOCAL_ENVIRONMENT = oldEnv; // do not forget to do this
    });

    test('do the thing', () => {
      doTheThing(); // process.env.LOCAL_ENVIRONMENT is 'test' here
    });
  });
});
Robin Michay
  • 679
  • 3
  • 4
  • tried this. and while it does change the environment variable, the imported file that is being tested, does not see this. `let localEnv = (process.env.LOCAL_ENVIRONMENT).toLowerCase() === 'prod' ? 'prod' : 'stage';` is ALWAYS `prod` even when using the above method. – CoryDorning Feb 15 '22 at 14:52
  • My bad, I misunderstood your problem. I wanted to answer to the title ("Change process.env variable for single test using JEST"). This way will only work if you're getting the env dynamically in a function, not at the import. Be careful by using your solution, it may be hard to maintain in a long term, reimporting each file using process.env every time you're editing the process.env variables. But this is the only way to make it works because of the implementation. – Robin Michay Feb 16 '22 at 20:12