user2821242
user2821242

Reputation: 1181

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

Upvotes: 28

Views: 48603

Answers (2)

Paul F. Wood
Paul F. Wood

Reputation: 1775

There's no need to mock, which is something of a broad sword, since it works at the module level. Jest's spyOn is a more focussed way of doing this, since it is at the method level.

The confusion here is solely because of the internal workings of 'xyz'. You have assumed that the module called 'xyz' has a function within it also called 'xyz'. Hence Jest fails to find it.

If we assume that 'xyz' is actually the default export of the 'xyz' module, we can test using this:

const mock = jest.spyOn(myModule, 'default')

All of the rest of your test code is perfect:

mock.mockReturnValue('mocked value')
const op = calculate()
expect(op).toBe('mocked value')

Upvotes: -1

Andreas Köberle
Andreas Köberle

Reputation: 111062

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')
  }
})

Upvotes: 11

Related Questions