user3142695
user3142695

Reputation: 17352

JS/JestJS: How to test for a async mocked function?

As you can see in my testfile I've mocked all mongoDB methods.

Now I need to test, if Content.update() has been called. In this example code I'm testing for a called console.log which is working, but not want I want. I don't understand why I can't test for update()

/category.test.js

import { updateCategory } from './category'
import DB from './lib/db'

test('should update document', async () => {
  DB.getDB = jest.fn(
    () => ({
      get: jest.fn(
        () => ({
          findOne: jest.fn(() => ({ some: 'content' })),
          update: jest.fn()
        })
      )
    })
  )
  console.log = jest.fn()

  return updateCategory({}, {
    id: '12345678901234567'
  }).then(() => {
    expect(console.log).toHaveBeenCalled()
    // instead check if `Content.update()` has been called
    expect(DB.getDB().get().update).toHaveBeenCalled() // throws `Expected mock function to have been called.`
  })
})

/category.js

import DB from './lib/db'

export async function updateCategory (obj, { id }) {
  const db = DB.getDB()
  const Content = db.get('content')
  const doc = await Content.findOne({ _id: id })

  console.log('ok');

  await Content.update(
    { _id: id },
    { $set: { category: 'new category' } }
  )
}

Upvotes: 2

Views: 171

Answers (1)

stone
stone

Reputation: 8662

Store the mock you want to spy on in a variable so you can track it:

import { updateCategory } from './category'
import DB from './lib/db'
jest.mock('./lib/db');

const mockUpdate = jest.fn();

test('should update document', async () => {
  DB.getDB.mockImplementation( // <-- available when you call jest.mock above, seems safer than overwriting the implementation in the real import
    () => ({
      get: jest.fn(
        () => ({
          findOne: jest.fn(() => ({ some: 'content' })),
          update: mockUpdate
        })
      )
    })
  )
  console.log = jest.fn()

  return updateCategory({}, {
    id: '12345678901234567'
  }).then(() => {
    expect(console.log).toHaveBeenCalled()
    // instead check if `Content.update()` has been called
    expect(mockUpdate).toHaveBeenCalled() // should work now
  })
})

Upvotes: 3

Related Questions