0

I'm having trouble trying to mock a constructor Function.

Here is the main class that I want to test

// main.js

import { Handler } from './handler/handler.js';
var lh = new Handler(windowAlias, documentAlias);
   // rest of code

Here is how my Handler function looks. Im trying to mock this

//handler.js
export function Handler(windowAlias, documentAlias) {
  this.windowAlias = windowAlias;
  this.documentAlias = documentAlias;

  this.attachEventListners = function(globalSet) {
    // do something
  };
}

And the test code:

// main.test.js
   import { Handler } from 'handlers/handler'

   describe('main script', () => {

       it('test handler', () => {
            jest.mock('handlers/handler', () => jest.fn())
            const mockEventListner = jest.fn()
            Handler.mockImplementation(() => ({mockEventListner}))

            //call main.js

            expect(mockEventListner).toBeCalledTimes(1);
})

I referred this stack overflow and tried but now Im getting error like _handler.Handler is not a constructor on the line that does new Handler(). How can I mock the new Handler call when its a constructor function

Lin Du
  • 88,126
  • 95
  • 281
  • 483
TestingInProd
  • 349
  • 10
  • 26

1 Answers1

2

You could use jest.mock(moduleName, factory, options) to mock ./handler/handler.js module and Handler class manually.

E.g.

main.js:

import { Handler } from './handler/handler.js';

const windowAlias = 'windowAlias';
const documentAlias = 'documentAlias';
var lh = new Handler(windowAlias, documentAlias);

handler/handler.js:

export function Handler(windowAlias, documentAlias) {
  this.windowAlias = windowAlias;
  this.documentAlias = documentAlias;

  this.attachEventListners = function(globalSet) {
    // do something
  };
}

main.test.js:

import './main';
import { Handler } from './handler/handler.js';
jest.mock('./handler/handler.js', () => {
  return { Handler: jest.fn() };
});

describe('64382021', () => {
  it('should pass', async () => {
    expect(Handler).toBeCalledWith('windowAlias', 'documentAlias');
  });
});

unit test result:

 PASS  src/stackoverflow/64382021/main.test.js
  64382021
    ✓ should pass (6ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        4.093s, estimated 10s
Lin Du
  • 88,126
  • 95
  • 281
  • 483
  • how is this possible, wouldn't the constructor be called before the test has a chance to mock it? – sezanzeb Dec 06 '22 at 11:14
  • 1
    "Jest will automatically hoist jest.mock calls to the top of the module (before any imports)", see https://jestjs.io/docs/manual-mocks#using-with-es-module-imports – sezanzeb Dec 06 '22 at 14:32