Jest未执行TypeScript模块末尾静态方法的问题排查
问题:测试中Builder实例返回undefined的排查与解决
代码文件
Builders.ts
// Builders.ts import {Registry} from "./Registry"; export interface IBuilder { build: () => void; } class NiceBuilder implements IBuilder { build(): void { console.log('Nice builder') } } class SuperBuilder implements IBuilder { build(): void { console.log('Super Builder') } } Registry.registerBuilder(new NiceBuilder()); Registry.registerBuilder(new SuperBuilder());
Registry.ts
// Registry.ts import {IBuilder} from "./Builders"; export class Registry { static builders: Array<IBuilder> = []; static registerBuilder(builder: IBuilder) { this.builders.push(builder); } static getBuilder(): IBuilder { return this.builders[0]; } }
Builder.test.ts
// Builder.test.ts import {Registry} from "../../../Registry"; import {IBuilder} from "../../../Builders"; describe('test builders', () => { it('test', () => { const builder: IBuilder = Registry.getBuilder(); console.log(builder); // logs undefined why??????? }); });
问题原因
- Builders.ts未被实际加载执行:测试文件仅导入了
IBuilder接口,而TypeScript接口编译为JavaScript后会被完全移除,运行时不会触发Builders.ts的顶层代码执行——你期望的注册逻辑根本没运行。 - 循环依赖隐患:Registry.ts和Builders.ts互相导入,即便加载了Builders.ts,也可能因循环依赖导致注册逻辑执行时机异常,出现实例未被正确添加的情况。
解决思路
强制加载Builders.ts:在测试文件中直接导入Builders.ts,无需使用它的任何导出内容,确保运行时执行注册逻辑:
// Builder.test.ts import {Registry} from "../../../Registry"; import {IBuilder} from "../../../Builders"; import "../../../Builders"; // 新增此行,触发文件执行 describe('test builders', () => { it('test', () => { const builder: IBuilder = Registry.getBuilder(); console.log(builder); // 现在会输出NiceBuilder实例 }); });拆分接口解决循环依赖(推荐):把
IBuilder接口抽成独立文件,避免Registry和Builders互相导入:- 创建
BuilderTypes.ts:// BuilderTypes.ts export interface IBuilder { build: () => void; } - 修改Registry.ts:
// Registry.ts import {IBuilder} from "./BuilderTypes"; export class Registry { static builders: Array<IBuilder> = []; static registerBuilder(builder: IBuilder) { this.builders.push(builder); } static getBuilder(): IBuilder { return this.builders[0]; } } - 修改Builders.ts:
// Builders.ts import {Registry} from "./Registry"; import {IBuilder} from "./BuilderTypes"; class NiceBuilder implements IBuilder { build(): void { console.log('Nice builder') } } class SuperBuilder implements IBuilder { build(): void { console.log('Super Builder') } } Registry.registerBuilder(new NiceBuilder()); Registry.registerBuilder(new SuperBuilder());
- 创建
这样既解决了测试中注册逻辑不执行的问题,也消除了循环依赖带来的潜在风险。
内容的提问来源于stack exchange,提问作者whitefang1993
相关产品推荐
相关产品推荐

