Amico
Amico

Reputation: 803

how to reset module imported between tests

let's say I have a module that needs to be initialized once in the start of the app (to pass on configuration). module will look something like this :

MyModule.js

let isInitiazlied;

const myModule = {

    init: function() {
        isInitiazlied = true;
    },
    do: function() {
        if (!isInitiazlied)
            throw "error"
        //DO THINGS
    }
}

export default myModule;

I want to unittest it, using jest. test file looks something like this :

MyModule.test.js

import myModule from './MyModule'

describe('MyModule', () => {
    describe('init', () => {
        it('not throws exception when called', () => {
            expect(() => myModule.init()).not.toThrow();
        });
    })
    describe('do', () => {
        it('throw when not init', () => {
            expect(() => myModule.do()).toThrow();
        });
    })
})

when I run the test, the 2nd test fail, as the module already initialized so the exception is not thrown. I tried using jest.resetModules() in beforeEach, but that didn't work.

Is there a way to solve it (different module pattern/test case) ?

Upvotes: 55

Views: 56750

Answers (5)

Kevin
Kevin

Reputation: 1483

A solution that worked well for me and allowed me to continue using canonical top-of-the-file imports: I added a function

export function resetIsInitializedForTests() {
  isInitialized = false
}

to MyModule.js and then I called it inside beforeEach in MyModule.test.js.

Upvotes: 0

MG Developer
MG Developer

Reputation: 918

Resetting the process.env does not work very well with Jest across all Node platforms. After trying various options I realized there is a very simple fix to solve this issue using regular jest mock by adding a wrapper function for retrieving process.env. This will avoid having unexpected behaviors cross platforms.

Those who are new to Jest here is a complete solution. Add a JS file nodeEnvironment.js with the function as follows

const getNodeEnvironment = () => {
  return process.env;
};

export default getNodeEnvironment;

Then import the getNodeEnvironment function as normally you would do.

import getNodeEnvironment from './nodeEnvironment';

const myMainFunction= () => {
     const env = getNodeEnvironment();
     const myVarVal = env.myVar    
 }

and then use the jest mock. Please note you will need to set esModule flag to true if you want your function to be default export and then add return default: mockvalue as follows.

jest.mock('./nodeEnvironment', () => ({
  __esModule: true,
  default: () => {
    //here set all variables you need for your tests
    const env = { myVar: "123" }; 
    return env;
  },
}));

Upvotes: -1

ltamajs
ltamajs

Reputation: 1341

You have to re-import or re-require your module. Check the doc or this issue for more information:

https://github.com/facebook/jest/issues/3236

https://jestjs.io/docs/jest-object#jestresetmodules

describe('MyModule', () => {
    beforeEach(() => {
        jest.resetModules()
    });

    describe('init', () => {
        const myModule = require('./MyModule');

        it('not throws exception when called', () => {
            expect(() => myModule.init()).not.toThrow();
        });
    })
    describe('do', () => {
        const myModule = require('./MyModule');

        it('throw when not init', () => {
            expect(() => myModule.do()).toThrow();
        });
    })
})

Upvotes: 71

Anant Jain
Anant Jain

Reputation: 21

In my case only re-requiring didn't work. I got through jest documentation and found this. This suggest use of jest.resetModules(). This basically just resets the cache and on re-requiring module it makes sure it gets loaded from scratch. So when ever you want are re-requiring use this to make sure the it is getting loaded from scratch

Upvotes: 0

Lucio
Lucio

Reputation: 5408

@ltamajs solution is great for require but in the case you are using import then you will receive the next error.

SyntaxError: /path/to/test/file.js: 'import' and 'export' may only appear at the top level

To solve this issue, you can use the babel-plugin-dynamic-import-node plugin and then reset the modules. Overall, it looks like this:

describe('MyTests', () => {
  let MyModule;

  beforeEach(() => {
    return import('../module/path').then(module => {
      MyModule = module;
      jest.resetModules();
    });
  });

  test('should test my module', () => {
    expect(MyModule.aMethod).not.toBeUndefined();
  });
});

Source: https://github.com/facebook/jest/issues/3236#issuecomment-698271251

Upvotes: 19

Related Questions