Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does jest not mock this module?

I have a module that's supposed to call a local fetch wrapper. To check whether the get module calls the fetch wrapper correctly I'm mocking it and returning a spy like so:

// get.js
import fetch from '../fetch'

const get = (endpoint, token) => {
  const headers = new Headers()

  if (token) {
    headers.append('Authorization', `Bearer ${token}`)
  }

  const init = {
    headers,
    method: 'GET'
  }

  return fetch(new Request(endpoint, init))
}

export default get
// get.test.js
import 'isomorphic-fetch'
import get from './get'

describe('get', () => {
  it('calls fetch with a request', () => {
    // I'm expecting this spy to be called by get
    const mockFetch = jest.fn()
    jest.mock('../fetch', () => jest.fn(mockFetch))

    get('endpoint', 'token')

    expect(mockFetch).toHaveBeenCalled()
  })
})

But when I run it jest fails with:

expect(jest.fn()).toHaveBeenCalled()

Expected mock function to have been called.

So why isn't it calling the mock?


1 Answers

The problem is that all jest.mock statements are hoisted to the top of code block. So even if you write it into the middle of your test it will be run as the first statement of your test and there is no way to have a specific return value. So how to fix this? First put the mock statement after your import statements to make clear that the mocking not happening in the test. Then import the module in your test. So this will be the result of the jest.fn() in your mock statement. As fetch is a spy now you can test on this that fetch was called.

import 'isomorphic-fetch'
import get from './get'
import fetch from '../fetch'
jest.mock('../fetch', () => jest.fn())

describe('get', () => {
  it('calls fetch with a request', () => {
    get('endpoint', 'token')
    expect(fetch).toHaveBeenCalled()
  })
})
like image 72
Andreas Köberle Avatar answered Oct 21 '25 00:10

Andreas Köberle