9

I find that when using jest.doMock instead of jest.mock to mock a function (I will need to create multiple mock implementations for the same function in different it blocks), I find that the test fails with

Error

expect(jest.fn()).toBeCalled()

Expected mock function to have been called.

Also, if I require the module at the top of the test instead of doing it within the same it block, it gives me a different error:

expect(jest.fn())[.not].toBeCalled()

jest.fn() value must be a mock function or spy.
Received:
  function: [Function headObject]

Code

  1. headObject(Collaborator being mocked)

    // NOT IMPLEMENTED YET
    module.exports = function() {}
    
  2. Test code

    it('checks to see if a resource exists when given a threshold', () => {
      jest.doMock('../s3/headObject', () => {
        return jest.fn(() => {})
      })
      const headObject = require('../s3/headObject')
      handler(event.correct_uses_propertyId_withExplicitThreshold, {}, () => {})
      expect(headObject).toBeCalled()
    })
    
  3. Source Code

    const headObject  = require('../s3/headObject')
      module.exports = async function(event, context, callback) {
       headObject()
    }
    

Previously

I used environment variables to change the mock implementation using mocks within __mocks__ like this:

const result = jest.genMockFromModule('../realModule.js')
const mockResponse = require('../../eventMocks/realModuleName/fixture.json')

function mock (bearerToken, address) {
  if (process.env.DONT_USE_TEST_ONLY_EMPTY_ESTIMATE) {
    return {
      history: []
    }
  }
  return mockResponse
}

result.mockImplementation(mock)

module.exports = result

and in my test, I would:

it('does not store empty results in S3', () => {
  process.env.DONT_USE_TEST_ONLY_EMPTY_ESTIMATE = true
  const res = LambdaTester(handler)
  .event(event.correct_uses_address)
  .expectResult(r => {
    expect(r.statusCode).toEqual(404)
    const body = JSON.parse(r.body)
    expect(body.message).toEqual(NO_ESTIMATE)
  })

  process.env.DONT_USE_TEST_ONLY_EMPTY_ESTIMATE = false
  return res
})
vamsiampolu
  • 6,328
  • 19
  • 82
  • 183

1 Answers1

2

Late to the party.... doMock is a pain. We use this setup within our tests:

// import function from module you want to mock
import getClientVersion from '../api/clientVersion';

// mock the whole module
jest.mock('../api/clientVersion');


// within a test, overwrite that specific function
getClientVersion.mockResolvedValueOnce(1);

Good thing with this is, that you can easily change the setup in each test.

Hope this helps someone who stumbles upon this questions

flaky
  • 6,816
  • 4
  • 29
  • 46
  • I was confused when I searched for `doMock` (since I had used it before) and didn't find it in the jest docs This seems like a reasonable strategy! – JuanCaicedo Sep 03 '20 at 17:12
  • 1
    adding a downvote because, while this is useful, it doesn't answer the question that was asked – Switch386 Mar 02 '21 at 00:20