Home > Net >  Why is Jest claiming a mocked function isn't being called when it clearly is?
Why is Jest claiming a mocked function isn't being called when it clearly is?

Time:11-19

I have a simple function which sends an array to a logger:

const logger = require('../../../common/lib/logger')();

const displayErrors = async (errors) => {
  const promisesToWriteData = [];

  errors.forEach((error) => {
    console.log({error});
    promisesToWriteData.push(logger.error(`${error[0]}: ${error[1]} - Customer: ${error[2]}`));
  });
  await Promise.all(promisesToWriteData);
};

I use jest to check that the logger is being called:

const logger = require('../../../../common/lib/logger');

jest.mock('../../../../common/lib/logger');

const logInfoMock = jest.fn();
const logErrorMock = jest.fn();
logger.mockImplementation(() => ({
  info: logInfoMock,
  error: logErrorMock,
}));

const { displayErrors,} = require('../../lib/verification-utils');

const errorArray = [
  [
    'customerData.PaymentDetails.CasePaymentGroup.PAXNominee',
    'NomineeID missing',
    'example4',
  ],
  [
    'customerData.PaymentDetails.CasePaymentGroup.PAXNominee',
    'Comments missing',
    'example4',
  ],
];

describe('Display errors', () => {
  it('should send errors to the logger when there are errors in the error array', async () => {
    const flushPromises = () => new Promise(setImmediate);
    await displayErrors(errorArray);
    await flushPromises();
    expect(logger).toHaveBeenCalledTimes(2);
  });
});

And getting the following error when running the unit test:

expect(jest.fn()).toHaveBeenCalled()

    Expected number of calls: >= 2
    Received number of calls:    0

      34 |     await displayErrors(errorArray);
      35 |     await flushPromises();
    > 36 |     expect(logger).toHaveBeenCalled();
         |                    ^
      37 |   });
      38 | });
      39 |

The console.log call in the function shows me the array that is about to be sent to logger, so I know that the code is definitely reaching there.

This originally was not an asynchronous function and I see no reason why it should be. I only made it thus because that, along with all the guff about promises in the unit test, was supposedly a fix for this problem .

CodePudding user response:

Are u trying to test if logger.error have been call?

Can you try this?

const logger = require('../../../../common/lib/logger');
// change here
jest.mock('../../../../common/lib/logger',() => {
  return {
    info: jest.fn(),
    error: jest.fn()
  }
});


const { displayErrors,} = require('../../lib/verification-utils');

const errorArray = [
  [
    'customerData.PaymentDetails.CasePaymentGroup.PAXNominee',
    'NomineeID missing',
    'example4',
  ],
  [
    'customerData.PaymentDetails.CasePaymentGroup.PAXNominee',
    'Comments missing',
    'example4',
  ],
];

describe('Display errors', () => {
  it('should send errors to the logger when there are errors in the error array', async () => {
    const flushPromises = () => new Promise(setImmediate);
    await displayErrors(errorArray);
    await flushPromises();
    // change here  
    expect(logger.error).toHaveBeenCalledTimes(2);
  });
});
  • Related