Invalidate node cache when using Jest

30,904

Solution 1

You can use jest.resetModules() in beforeEach method to reset the already required modules

beforeEach(() => {
  jest.resetModules()
  process.env = { ...OLD_ENV };
  delete process.env.NODE_ENV;
});

Solution 2

Instead of resetting all modules, you can require modules in isolation by using jest.isolateModules(fn).

For example:

test('are string values (to avoid casting errors)', () => {
  jest.isolateModules(() => {
    const { ENV } = require(envFilePath);
    Object.values(ENV).forEach(val => expect(typeof val).toEqual('string'));
  });
});
Share:
30,904

Related videos on Youtube

Tomasz Mularczyk
Author by

Tomasz Mularczyk

I'm a man of many interests. https://www.linkedin.com/in/tomaszmularczyk/ https://github.com/Tomekmularczyk https://medium.com/@tomaszmularczyk89

Updated on February 25, 2022

Comments

  • Tomasz Mularczyk
    Tomasz Mularczyk about 2 years

    I have a file with object that gets populated with process.env properties:

    env.js

    console.log('LOADING env.js');
    
    const {
      PROXY_PREFIX = '/api/',
      USE_PROXY = 'true',
      APP_PORT = '8080',
      API_URL = 'https://api.address.com/',
      NODE_ENV = 'production',
    } = process.env;
    
    const ENV = {
      PROXY_PREFIX,
      USE_PROXY,
      APP_PORT,
      API_URL,
      NODE_ENV,
    };
    
    module.exports.ENV = ENV;
    

    Now I try to test this file with different process.env properties:

    env.test.js

    const envFilePath = '../../config/env';
    
    describe('environmental variables', () => {
      const OLD_ENV = process.env;
    
      beforeEach(() => {
        process.env = { ...OLD_ENV };
        delete process.env.NODE_ENV;
      });
    
      afterEach(() => {
        process.env = OLD_ENV;
      });
    
      test('have default values', () => {
        const { ENV } = require(envFilePath);
        expect(ENV).toMatchSnapshot();
      });
    
      test('are string values (to avoid casting errors)', () => {
        const { ENV } = require(envFilePath);
        Object.values(ENV).forEach(val => expect(typeof val).toEqual('string'));
      });
    
      test('will receive process.env variables', () => {
        process.env.NODE_ENV = 'dev';
        process.env.PROXY_PREFIX = '/new-prefix/';
        process.env.API_URL = 'https://new-api.com/';
        process.env.APP_PORT = '7080';
        process.env.USE_PROXY = 'false';
    
        const { ENV } = require(envFilePath);
    
        expect(ENV.NODE_ENV).toEqual('dev');
        expect(ENV.PROXY_PREFIX).toEqual('/new-prefix/');
        expect(ENV.API_URL).toEqual('https://new-api.com/');
        expect(ENV.APP_PORT).toEqual('7080');
        expect(ENV.USE_PROXY).toEqual('false');
      });
    });
    

    Unfortunately, even though I try to load the file in every test separately the file gets loaded only once, making the third test fail with:

    Expected value to equal:
      "dev"
    Received:
      "production"
    

    P.S. It doesn't fail when I run the test alone.

    I also know that env.js loads only once because console.log('LOADING env.js'); gets fired only once.

    I tried to invalidate Nodes cache like:

      beforeEach(() => {
        delete require.cache[require.resolve(envFilePath)];
        process.env = { ...OLD_ENV };
        delete process.env.NODE_ENV;
      });
    

    but require.cache is empty {} before each test so it seems that Jest is somehow responsible for importing the file.

    I also tried to run yarn jest --no-cache but didn't help.

    So what I want is to load env.js before each test so I can test how it behaves with different node environmental variables.

    jest@^22.0.4

    • Prakash Sharma
      Prakash Sharma over 6 years
      Which version of jest are you using?
    • Tomasz Mularczyk
      Tomasz Mularczyk over 6 years
      @Prakashsharma 22.0.4
    • Prakash Sharma
      Prakash Sharma over 6 years
      Try using jest.resetModules() in beforeEach. facebook.github.io/jest/docs/en/…
    • Tomasz Mularczyk
      Tomasz Mularczyk over 6 years
      @Prakashsharma thank U! Post an answer and I will accept it. Weird I missed that though.