Search code examples
javascriptunit-testingjestjsjest-fetch-mock

Jest: How to spy on an imported function


Putting in a small snippet below :

import xyz from '../xyz'
function calculate() {
  return xyz(arg1, arg2).catch((err) => {
    func1()
    func2()
  })
}
export default calculate

I'm just trying to assert that xyz is called in jest. How can I do it ?

I tried the following but doesn't work :

import * as myModule from '../xyz'
import calculate from '../../calculate'
const mock = jest.spyOn(myModule, 'xyz')
mock.mockReturnValue('mocked value')
const op = calculate()
expect(op).toBe('mocked value')

This gives me the following error:

Cannot spy the xyz property because it is not a function; undefined given instead


Solution

  • You can mock the module like this:

    import calculate from '../../calculate'
    jest.mock('../xyz', ()=> () => Promise.resolve('mocked value'))
    
    it('does something', async()=>{
      const op = await calculate()
      expect(op).toBe('mocked value')
    })
    
    

    if you need different return values from your mock you need to mock the module so it returns a spy. Then you have to import the module and you can set the return value during your tests:

    import calculate from '../../calculate'
    import myModule from '../xyz'
    jest.mock('../xyz', ()=> jest.fn())
    
    it('does something', async() => {
      myModule.mockImplementation(() => () =>  Promise.resolve('mocked value'))
    
      const op = calculate()
      expect(op).toBe('mocked value')
    })
    
    it('does something else', async() => {
      myModule.mockImplementation(() => () =>  Promise.resolve('another value'))
      const op = await calculate()
      expect(op).toBe('another value')
    })
    
    
    it('does fail', async() => {
      myModule.mockImplementation(() => () =>  Promise.reject('some Error')
      try{
        const op = await calculate()
      }catch (e){
        expect(e).toBe('some Error')
      }
    })