Jest无法覆盖NestJS用例层insert参数中的回调函数
解决NestJS用例层回调函数Jest覆盖率统计问题
问题出在哪
Jest默认不会追踪那些作为参数传给依赖方法的匿名回调的覆盖率,除非这些回调被实实在在执行了,而且测试代码能覆盖到执行的路径。
具体解决办法
1. 先确认回调真的被执行了
首先得检查moduleRepository.insert方法有没有真的调用传入的callBeforeInsert和callAfterInsert。如果是你自己写的Repository,查内部逻辑有没有触发这俩回调;如果是Mock的Repository,得在测试里手动模拟调用这两个回调。
举个Mock的例子:
// 测试文件里这么写 const moduleRepository = { insert: jest.fn(async (data, callbacks) => { // 手动调用before回调 await callbacks.callBeforeInsert(data); // 模拟插入操作 const result = { id: 1, ...data }; // 手动调用after回调 await callbacks.callAfterInsert(result); return result; }), };
2. 把回调抽成独立函数(推荐这么做)
别写匿名回调了,把它们改成独立的命名函数,Jest更容易追踪到执行路径,代码也更好维护。
改之前的代码:
// AddModuleUseCases.ts async execute(data: ModuleDto) { const callBeforeInsert = async (moduleData: ModuleDto) => { // 内部逻辑 moduleData.createdAt = new Date(); }; const callAfterInsert = async (savedModule: ModuleEntity) => { // 内部逻辑 await this.eventEmitter.emit('module.created', savedModule); }; return this.moduleRepository.insert(data, { callBeforeInsert, callAfterInsert }); }
改之后:
// AddModuleUseCases.ts private async callBeforeInsert(moduleData: ModuleDto) { moduleData.createdAt = new Date(); } private async callAfterInsert(savedModule: ModuleEntity) { await this.eventEmitter.emit('module.created', savedModule); } async execute(data: ModuleDto) { return this.moduleRepository.insert(data, { callBeforeInsert: this.callBeforeInsert.bind(this), callAfterInsert: this.callAfterInsert.bind(this), }); }
这样就算通过Mock Repository触发回调,Jest也能统计到这两个私有方法的覆盖率。
3. 调一下Jest配置(可选)
如果上面的方法没用,检查jest.config.js里的collectCoverageFrom配置,确保包含了你的用例层文件:
// jest.config.js module.exports = { collectCoverageFrom: [ 'src/**/*.use-cases.ts', // 匹配你的用例层文件路径 'src/**/*.service.ts', '!src/**/*.module.ts', '!src/main.ts', ], };
同时注意别在coveragePathIgnorePatterns里把这些文件排除了。
4. 直接测试回调函数(针对私有方法)
如果回调是私有方法,可以用jest.spyOn来拿到并调用它:
// 测试文件 it('should run callBeforeInsert correctly', async () => { const useCase = new AddModuleUseCases(moduleRepository, eventEmitter); // 监听私有方法 const beforeSpy = jest.spyOn(useCase as any, 'callBeforeInsert'); const testData = { name: 'test module' }; await useCase.execute(testData); expect(beforeSpy).toHaveBeenCalledWith(testData); expect(testData.createdAt).toBeInstanceOf(Date); });
内容的提问来源于stack exchange,提问作者user3354853
相关产品推荐
相关产品推荐

