Mocked module function with Jest is never called

Viewed 530

I have a really weird situation where my Jest tests are passing in my Windows 10 desktop and Macbook Pro, but they are not passing in 2 of my other friends' Windows 10 desktops.

Code that is being tested

import { addTerminalItem } from '../../store'
...
class LoginUser extends EventHandler {
  ...
  async handle () {
    if (this.isFromOauthRedirect) {
      try {
        await this._handleOauthRedirect()
      } catch (e) {
        addTerminalItem(new ErrorMessage(e.message))
      }
      return
    }

    if (await zaClient.isUserLoggedIn('testUserId')) {
      // TODO: user is already logged in, do something
    } else {
      const loginStartSecret = uuidv4()
      localStorage.setItem(LOGIN_START_SECRET, loginStartSecret)
      addTerminalItem(new LoginMessage(loginStartSecret))
    }
  }
  ...
}

export const loginUser = new LoginUser()

The testing code does the following:

  1. Adds invalid LOGIN_START_SECRET so that actual code throws exception entering the first catch.
  2. Subscribes the event handler to the event WELCOME_MESSAGE_RENDERED.
  3. Mocks the store.addTerminalItem module function.
  4. Publishes the event so the above async handle() function is triggered.
  5. Checks that the mocked function is called.

import * as store from '../../../store'
...
test('different login start secret in localstorage', async () => {
  localStorage.setItem(LOGIN_START_SECRET, 'different-secret')
  zaClient.login = jest.fn(() => true)
  store.addTerminalItem = jest.fn()

  await pubsub.publish(WELCOME_MESSAGE_RENDERED)

  expect(store.addTerminalItem).toHaveBeenCalledWith(expect.any(ErrorMessage))
  const errorMessage = store.addTerminalItem.mock.calls[0][0]
  expect(errorMessage.message).toBe(loginSecurityErrorMsg)
})

As I said on my computer it shows correctly that addTerminalItem function is called once with the correct argument on both machines I have at home. However this mocked function is never called and fails on 2 of my friends' machines. The actual error message they get is below:

expect(jest.fn()).toHaveBeenCalledWith(...expected)

Expected: Any<ErrorMessage>

Number of calls: 0

Here are the following things we tried so far:

  • Fresh git clone, yarn install, and yarn test. I pass and they don't.
  • With addTerminalItem mocked, we added a console.log inside addTerminalItem and it correctly doesn't log, but still 0 number of calls.
  • With addTerminalItem spyed, we added a console.log inside addTerminalItem and it correctly logs, but still 0 number of calls (this makes no sense to me)
  • We matched our yarn version.
  • We carefully debug stepped through the code to make sure all other things were working as expected.

If anyone could give us any pointers here it would be greatly appreciated.

1 Answers

Hard to be definitive without the code at hand, but try using jest.mock:

import {addTerminalItem} from "../../../store";

jest.mock('../../../store', () => ({
  addTerminalItem: jest.fn() 
));

//... stuff ...

test('different login start secret in localstorage', async () => {
  localStorage.setItem(LOGIN_START_SECRET, 'different-secret')
  zaClient.login = jest.fn(() => true)
  
  await pubsub.publish(WELCOME_MESSAGE_RENDERED)

  expect(addTerminalItem).toHaveBeenCalledWith(expect.any(ErrorMessage))
  const errorMessage = addTerminalItem.mock.calls[0][0]
  expect(errorMessage.message).toBe(loginSecurityErrorMsg)
})
Related