Home > Net >  How to mock module level instance
How to mock module level instance

Time:11-17

I have this code that need to test

import Logger from './logger';

const logger = new Logger();

export function myFunction() {
  // do something
  logger.log('Hello');
}

How to test if function myFunction has called logger.log? This is what I ve tried but failed

jest.mock('./logger');
const mockedLoggerClass = <jest.Mock>Logger;

describe('Test myFunction', () => {
  it('should call logger log', () => {
    const loggerInstance = {
       log: jest.fn()
    }

    mockedLoggerClass.mockReturnValue(() => loggerInstance);
    myFunction()
    expect(loggerInstance.log).toBeCalled; // Nope no call
  });

})

here is another try

const loggerInstance = {
   log: jest.fn()
}
jest.mock('./logger', () => {
  return function () {
    return loggerInstance;  // ReferenceError: Cannot access 'loggerInstance' before initialization
  }
});

describe('Test myFunction', () => {
  it('should call logger log', () => {
 
    myFunction()
    expect(loggerInstance.log).toBeCalled;
  });

})

I know we should not init logger as global scope but this is not my code so I cannot touch it.

CodePudding user response:

Your loggerInstance and the logger in the production code are not the same references. logger variable will be created right after you import myFunction, then you have to get this Logger instance instead of trying to mock another instance.

To do it, you can get a mock instance by jest:

import { myFunction } from './index'; // a mocked logger already created
import Logger from './logger';

jest.mock('./logger'); // mock it

describe('myFunction', () => {
  let logger: jest.Mocked<Logger>;

  beforeEach(() => {
    logger = (Logger as jest.Mock).mock.instances[0]; // get the mocked instance
  });

  it('should call Logger.log function with "Hello"', () => {
    myFunction(); // action

    expect(logger.log).toBeCalledWith('Hello'); // expectation
  })
});

You create a dependency (logger) in a high component (myFunction), this is an anti dependence injection pattern, which makes your code become hard to test. You can try module pattern, just export default new Logger() instead of export default class Logger...

  • Related