Reputation: 1077
I have code that I am writing tests for to refactor later, as such I cannot change the code or any of the dependencies. Here is the problem:
// foo.js
Knex = require('knex')
module.exports ={func}
// calling this inside func will
// have the expected {a:4}
client = Knex()
async function func(){
console.log(client)
return true
}
// foo.spec.js
const foo = require('./foo')
const Knex = require('knex')
jest.mock('knex', ()=>jest.fn())
describe('jest.mockImplementation',()=>{
it('should mock knex',async ()=>{
Knex.mockImplementation(()=>({a:4}))
// alternative, I can put
// const foo = require('./foo')
// here
await foo.func()
})
})
// jest.config.js
module.exports={
"verbose": true,
"testEnvironment": "node",
}
//package.json
{
"dependencies": {
"jest": "^26.6.3",
"knex": "0.19.3"
}
}
I run:
$ jest --config jest.config.js --runInBand foo.spec.js
and I expect there to be a console log of { a : 4}
, but it is undefined
. Note however, if I move the client
inside func
then it will log {a : 4}
alternatively, if I leave the client
where it is and require
foo
in spec.js
after mockImplementation
, it will again have the expected console log.
I would have expected to see the correct behavior with the client
being created outside of func
and without needing to require
foo
after mockImplementation
.
Why is this happening and how can I have the desired behavior without moving the client
? also require
ing inside the function is not the best.
I created this repl.it for experimentation; please don't update it for others' use:
https://replit.com/join/xmlwttzl-eminarakelian1
Upvotes: 0
Views: 211
Reputation: 102617
The code of the module scope will be executed immediately when the module is required, so it is too late to provide the mock implementation in the test case.
jest.mock()
will be hoisted to the top of the test file. It will be executed before the require
statement, so when the module is required, the mock implementation provided in jest.mock()
will be used.
Provide a mock implementation inside jest.mock()
like this:
const foo = require('./foo');
jest.mock('knex', () => jest.fn(() => ({ a: 4 })));
describe('jest.mockImplementation', () => {
it('should mock knex', async () => {
await foo.func();
});
});
test result:
PASS examples/66881537/foo.spec.js (6.347 s)
jest.mockImplementation
✓ should mock knex (15 ms)
console.log
{ a: 4 }
at Object.<anonymous> (examples/66881537/foo.js:8:11)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 6.789 s
Upvotes: 1