brewster
brewster

Reputation: 4492

how to mock a constructor being initiated from inside a method with jest

i have a script that defines 2 classes, and 1 gets instantiated from within the constructor of the other. how can i mock the nested constructor, so i can test the parent constructor?

export default class Foo {
  // i want to test this constructor...
  constructor() {
    new Bar
  }
}

export class Bar {
  // but mock this constructor
  constructor() {}
}

additionally, i am trying to spy on the Bar constructor, to assert that it has been called

i have tried several different approaches, but haven't been able to get the results i am looking for. i am new to the jest mocking library

Upvotes: 2

Views: 13045

Answers (1)

Lin Du
Lin Du

Reputation: 102257

Need to make a little modification to the module export statement. Then, we can use jest.spyOn(object, methodName) method to mock implementation for Bar class. Take a look at the code after compiling. We create the mocked Bar in the module export object and we use it in the Foo class. It has the same reference as the mocked one.

Recommend way:

  1. Dependency Injection
  2. Each file contains ONLY ONE class. So that we can use jest.mock or jest.doMock method to mock the class without modifying the module export statement.

E.g.

index.ts:

export default class Foo {
  constructor() {
    new exports.Bar();
  }
}

class Bar {
  constructor() {
    console.log('real Bar constructor implmentation');
  }
}

exports.Bar = Bar;

index.test.ts:

import * as mod from './';

console.log(mod);

describe('64549093', () => {
  it('should pass', () => {
    const BarConstructorMock = jest.spyOn(mod as any, 'Bar').mockImplementationOnce(() => {
      console.log('fake Bar constructor implmentation');
    });
    new mod.default();
    expect(BarConstructorMock).toBeCalled();
  });
});

unit test result:

 PASS  src/stackoverflow/64549093/index.test.ts (9.905s)
  64549093
    ✓ should pass (5ms)

  console.log src/stackoverflow/64549093/index.test.ts:3
    { default: [Function: Foo], Bar: [Function: Bar] }

  console.log src/stackoverflow/64549093/index.test.ts:8
    fake Bar constructor implmentation

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        11.751s, estimated 12s

About the configuration of jestjs, TypeScript, see example: https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/64549093

Upvotes: 6

Related Questions