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:
- Dependency Injection
- 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
Bar.prototype.constructor === Bar. So that it's a constructor doesn't offer any opportunities regarding testing. You cannot mock a variable that is used in the same module where it was defined, end of the story. That Foo constructor contains side effect and ignores Bar instance is potentially an antipattern and should be addressed in the first place. If there werethis.bar = new Baryou could assert it.