lundi 20 janvier 2020

Mocked modules use a different "cache" (or scope) for manual mocks in Jest

When I try to use manual mocks to replace a function inside the fs module, calling jest.mock('foo') will prevent the module foo from accessing the previously set data in the mocked fs module. Here's an example:

__mocks__/fs.js:

const fs = jest.genMockFromModule('fs');
const globalObject = {};
fs.__modifyGlobalObject = (key, value) => {
    globalObject[key] = value;
};
fs.__getGlobalObject = () => {
    return globalObject;
};
module.exports = fs;

app/index.js

const fs = require('fs');
console.log('APP: ', fs.__getGlobalObject());

tests/app.test.js:

it('', () => {
    //Making sure that everything will use our mocked implementation of the fs module
    jest.mock('fs');
    //Setting the global object in the mocked fs module
    require('fs').__modifyGlobalObject('foo', 'bar');
    //Mocking the app
    jest.mock('../app');
    const mockedApp = require('../app');
});

Jest's console output should return: APP: { foo: 'bar' }. Unfortunately, it returns an empty object. When I comment out or remove the line where I mock the app module: //jest.mock('../app'); or require it with jest.requireActual, I get the expected output.

Is there any workaround? If you wonder why would I ever want to do this, here's my motivation: I'm trying the same thing as in the provided example. The proposed method allows me to load a "fake" configuration before each test. Without it, my configuration module would access the filesystem each time I run the tests. Everything worked flawlessly until I started to mock my user modules with jest.mock. Of course, I could mock individual exported functions instead of whole modules, but what should I do with the modules that use module.exports = () => {...? In their case, the modules themselves become functions.

Aucun commentaire:

Enregistrer un commentaire