Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reset single module with Jest

jest.resetModules() clears the require cache for all modules but is there a way to clear it for just a single module? Can't use require.cache as Jest appears to bypass it.

I'm testing a Node module which is stateful (i.e. it relies on the fact that multiple calls to require return the same instance). For my test I need to reset the state of the module to test different scenarios. jest.resetModules() works but then I need to re-require some other mocked modules which didn't need to be reset.

like image 237
Tamlyn Avatar asked Aug 08 '17 15:08

Tamlyn


2 Answers

As explained in the question, jest.resetModules() resets the module cache, which is useful your module keeps some local state and you want to get rid of that state between tests.

The problem with resetModules is that it resets everything but sometimes you want only some of the modules to be reset.

Since Jest 24 you can now use the jest.isolateModules to do this.

Let's say you have a module that keeps state:

module.js

exports.a = 1
exports.add = function (a) {
  return exports.a += a;
}

module.test.js

test('adds 1 to counter', () => {
  jest.isolateModules(() => {
    const myModule = require('./module');
    expect(myModule.add(1)).toBe(2);
    expect(myModule.add(1)).toBe(3);
  });
});

test('adds 2 to counter', () => {
  jest.isolateModules(() => {
    const myModule = require('./module');
    expect(myModule.add(2)).toBe(3);
    expect(myModule.add(2)).toBe(5);
  });
});

Basically with after every jest.isolateModules() call, the next time the module is required it will be have a fresh state.

like image 138
Farid Nouri Neshat Avatar answered Nov 14 '22 14:11

Farid Nouri Neshat


An example of mocking modules (with factories) for some tests, and restoring for others within a test file

describe("some tests", () => {
  let subject;

  describe("with mocks", () => {
    beforeAll(() => {
      jest.isolateModules(() => {
        jest.doMock("some-lib", () => ({ someFn: jest.fn() })); // .doMock doesnt hoist like .mock does when using babel-jest
        subject = require('./module-that-imports-some-lib');
      });
    });

    // ... tests when some-lib is mocked
  });

  describe("without mocks - restoring mocked modules", () => {
    beforeAll(() => {
      jest.isolateModules(() => {
        jest.unmock("some-lib");
        subject = require('./module-that-imports-some-lib');
      });
    });

    // ... tests when some-lib is NOT mocked

  });
});
like image 23
Ben Avatar answered Nov 14 '22 15:11

Ben