Jest mock is undefined when inspecting it
I found what the issue is.
Because foo is instantiated by executing the function, calling mockFoo.met1 returns undefined since mockFoo is a function. For mock1 to be defined, I'd have to call mockFoo().met1. But at that point I'm getting a new instance of mockFoo which is different from the one loaded and called by moduleUnderTest.
To fix the problem, I have to declare and set the mock this way:
const mockMet1 = jest.fn()
const mockMet2 = jest.fn()
const mockFoo = () => ({
met1: mockMet1,
met2: mockMet2,
})
const moduleUnderTest = require('./moduleUnderTest')
jest.mock('../foo', mockFoo)
// ...snip...
afterEach(() => { // resets the called count etc
mockMet1.resetMock()
mockMet2.resetMock()
})
// ...snip...
expect(mockMet1).toHaveBeenCalledTimes(1)
// ...snip...
springloaded
Updated on June 04, 2022Comments
-
springloaded almost 2 years
I have a module that uses a second module. They're both custom modules, not NPM packages.
I want to make sure that
moduleUnderTest
calls a specific method fromfoo
.So I'm using
jest.mock
and I pass it a function that has the same signature asfoo
but contains jest spy functions instead of the actual implementation.I was under the impression that using
jest.mock
with themockFoo
object would inject the mockedfoo
instead of the actual module whenmoduleUnderTest
requiresfoo
.If I inspect what
foo
is from withinmoduleUnderTest
while the test is running, I can see that it is indeed my mocked foo.But when I get to the
expect
,mockedFoo.met1
becomes undefined.Why is that?
// ../foo/foo.js const foo = arg => { console.log(arg) return { met1: () => {}, met2: () => {}, } } module.exports = foo // ..foo/index.js // I am doing it this way so I can put the actual implementation in // several different files, but can require the whole module with // require('../foo') rather than require('../foo/foo') module.exports = require('./foo') // ./moduleUnderTest.js const foo = require('../foo')('hi') require('util').inspect(foo) // it seems that foo is indeed the mocked // version here[0] const moduleUnderTest = () => { foo.met1() } module.exports = moduleUnderTest // ./moduleUnderTest.test.js const moduleUnderTest = require('./moduleUnderTest') const mockFoo = () => ({ met1: jest.fn(), met2: jest.fn(), }) jest.mock('../foo') test('foo.met1 is called', () => { moduleUnderTest() expect(mockFoo.met1).toHaveBeenCalledTimes(1) // NOPE![1] }) // [0] // { met1: // { [Function: mockConstructor] // _isMockFunction: true, // getMockImplementation: [Function], // mock: [Getter/Setter], // mockClear: [Function], // mockReset: [Function], // mockReturnValueOnce: [Function], // mockResolvedValueOnce: [Function], // mockRejectedValueOnce: [Function], // mockReturnValue: [Function], // mockResolvedValue: [Function], // mockRejectedValue: [Function], // mockImplementationOnce: [Function], // mockImplementation: [Function], // mockReturnThis: [Function], // mockName: [Function], // getMockName: [Function], // mockRestore: [Function] }, // met2: // { [Function: mockConstructor] // _isMockFunction: true, // getMockImplementation: [Function], // mock: [Getter/Setter], // mockClear: [Function], // mockReset: [Function], // mockReturnValueOnce: [Function], // mockResolvedValueOnce: [Function], // mockRejectedValueOnce: [Function], // mockReturnValue: [Function], // mockResolvedValue: [Function], // mockRejectedValue: [Function], // mockImplementationOnce: [Function], // mockImplementation: [Function], // mockReturnThis: [Function], // mockName: [Function], // getMockName: [Function], // mockRestore: [Function] } } // [1] // expect(jest.fn())[.not].toHaveBeenCalledTimes() // // jest.fn() value must be a mock function or spy. // Received: undefined
-
Vivek Iyer about 2 yearsThis leads to an error -
The second argument of 'jest.mock' must be an inline function.
How do we resolve this ?