roscioli
roscioli

Reputation: 1230

How to create a mock that extends an actual module in jest

I have a mock in __mocks__/some-module.js that mocks the module I have called some-module. I would like to have this mock have the exact same functionality as the original module except for selected extensions.

For example, say the original module (in node_modules/some-module/index.js) looks like:

module.exports = {
    func: () => {
        someHttpRequest()
    },
    constants: {A: 1, B: 2}
}

But in my mock (in __mocks__/some-module.js) I want:

module.exports = {
    func: () => {
        // This is some overridden dummy function. It could be any function, doesn't matter.
    },
    constants: originalModule.constants // This is the line in which I am "extending" the original module's actual functionality
}

I tried requiring with const originalMock = require('some-module') in __mocks__/some-module.js but ran into an error:

Could not locate the bindings file. Tried:
 → path/node_modules/gc-stats/build/gcstats.node
 → path/node_modules/gc-stats/build/Debug/gcstats.node
 → path/node_modules/gc-stats/build/Release/gcstats.node
 → path/node_modules/gc-stats/out/Debug/gcstats.node
 → path/node_modules/gc-stats/Debug/gcstats.node
 → path/node_modules/gc-stats/out/Release/gcstats.node
 → path/node_modules/gc-stats/Release/gcstats.node
 → path/node_modules/gc-stats/build/default/gcstats.node
 → path/node_modules/gc-stats/compiled/6.3.1/darwin/x64/gcstats.node

Upvotes: 2

Views: 2679

Answers (2)

Amit Modi
Amit Modi

Reputation: 21

Hey I came across this while searching for something similar. jest provides a way to achieve this using requireActual.

you can reference the original module using requireActual like

__mocks__/some-module.js

module.exports = {
    func: () => {
        // Do stuff
    },
    constants: jest.requireActual('some-module').constants 
}

reference: https://jestjs.io/docs/jest-object#jestrequireactualmodulename

Upvotes: 2

Andreas Köberle
Andreas Köberle

Reputation: 111032

There is no way that a mock can extend the module it should mock. What happens is, that before the modules are load each other Jest rewrites the path, so every modules that imports some-module will get the mock. So in the end the mock tries to load itself and fails.

In most of the cases it is also not necessary to have a real implementation in the mock. In your example yo could replace the request with a function that returns a resolved promise, for example.

Another way would be to just import the module in your test and override the function, but this will only work if the module does not use the function direct after the import.

import MyModule from 'my-module`

MyModule.func = () => Promise.resolve('test123')

Upvotes: 0

Related Questions