Hi guys, I have a really strange issue and I am not able to understand what is going on.
I am trying to run unit tests with jest (v25.3.0). While I am importing @hapi/joi in one of my node files I get the following error:
โ Test suite failed to run
TypeError: Method Map.prototype.set called on incompatible receiver #<Map>
at Map.set (<anonymous>)
at Object.<anonymous>.module.exports.internals.clone (../node_modules/@hapi/hoek/lib/clone.js:74:20)
at Object.<anonymous>.module.exports.internals.clone (../node_modules/@hapi/hoek/lib/clone.js:99:31)
at Object.<anonymous>.module.exports.internals.clone (../node_modules/@hapi/hoek/lib/clone.js:99:31)
at Object.<anonymous>.module.exports.internals.clone (../node_modules/@hapi/hoek/lib/clone.js:99:31)
at Object.<anonymous>.module.exports.internals.clone (../node_modules/@hapi/hoek/lib/clone.js:99:31)
at Object.<anonymous>.exports.type (../node_modules/@hapi/joi/lib/extend.js:16:23)
at Object.<anonymous>.internals.Base.extend (../node_modules/@hapi/joi/lib/base.js:437:23)
at Object.<anonymous> (../node_modules/@hapi/joi/lib/types/alternatives.js:15:22)
at Object.<anonymous> (../node_modules/@hapi/joi/lib/index.js:21:23)
at Object.<anonymous> (app/controllers/v1/file-controller.ts:1353:41)
No test is running before the failure. The line in app/controllers/v1/file-controller.ts that is causing the issue is import * as Joi from '@hapi/joi';
Do you have any idea why this is happening, because I am stuck
Hoek has some specific logic to handle cloning maps. From the error, it seems that this logic is somehow circumvented. Probably due to something the typescript compiler jest does.
Hey I am encountering the same error, when I clear my jest mocks the code executes. Have you found a solution to this issue?
Edit:
Based off of what kanongil said, the Map object maybe getting mocked by jest?
I found out that the issue is that the Map object is being mocked by Jest. I found that the Map class becomes mocked when I make a call to mock a mongoose model using jest.mock(...). I solved this issue by passing a factory argument to the jest.mock function that created my mongoose models without touching the Map class. All of my tests seem to be passing fine now.
@ecoulson I'm having the same issue here, could you please explain a bit more about the solution?
@ecoulson I'd also really like a little more detail on how you worked around this if it isn't too much trouble :)
@ptrin @derkinderfietsen here's what's happening:
file-controller.ts will be importing a mongoose model such as ../model/file.ts.
Then inside file-controller.test.ts, that model would be mocked using an automatic mock.
...
jest.mock('../../model/file.ts') // automatic mock inadvertently mocks Map
...
describe('file controller', () => {
test('deletes file', async () => {
await fileController.delete('filename') // this calls `model/file.ts`'s delete method
})
...
})
What @ecoulson did was explicitly mock the used methods on model/file.ts using the a module factory.
...
jest.mock('../../model/file.ts', () => ({ delete: jest.fn() })) // Map no longer mocked
...
describe('file controller', () => {
test('deletes file', async () => {
await fileController.delete('filename') // this calls `model/file.ts`'s delete method
})
...
})
@auzwang Thanks, that's very helpful!
Most helpful comment
@ptrin @derkinderfietsen here's what's happening:
file-controller.tswill be importing a mongoose model such as../model/file.ts.Then inside
file-controller.test.ts, that model would be mocked using an automatic mock.What @ecoulson did was explicitly mock the used methods on
model/file.tsusing the a module factory.