Jest v27升级后FeathersJS NeDB服务报FSREQCALLBACK警告如何解决
解决方案
根本原因
Jest v27 版本默认开启了未关闭句柄检测逻辑,你项目中使用的NeDB数据库在开启autoload持久化存储时,会生成常驻的文件系统操作句柄,测试运行结束后没有主动释放,就会触发该警告。
推荐根治方案
方案1:测试环境改用内存模式NeDB
测试环境下不需要持久化存储数据,直接将NeDB改为内存运行模式即可完全消除文件句柄问题,同时还能提升测试运行速度。
在测试环境的Feathers配置中添加:
// 测试环境加载配置时添加 app.set('nedb', { inMemoryOnly: true, autoload: true });
方案2:测试前后主动清理资源
如果你需要在测试中使用持久化NeDB,可通过以下步骤处理:
- 修改
src/app.ts的导出逻辑,从导出单例app改为导出app工厂函数,避免跨测试用例的状态污染:
// src/app.ts 修改前 const app = feathers(); // 所有配置逻辑 export default app; // 修改后 export default () => { const app = feathers(); // 原来的所有配置逻辑原样移入 return app; }
- 调整测试用例代码,测试前创建新的app实例,测试结束后主动关闭所有NeDB连接:
import createApp from '../../src/app'; import { Application } from '@feathersjs/feathers'; describe('\'auth-sms\' service', () => { let app: Application; beforeAll(async () => { app = createApp(); // 等待所有NeDB实例加载完成 await Promise.all( Object.values(app.services).map(async (service: any) => { if (service?.Model?.loadDatabase) { await new Promise(resolve => service.Model.loadDatabase(resolve)); } }) ); }); afterAll(async () => { // 关闭所有NeDB实例释放句柄 await Promise.all( Object.values(app.services).map(async (service: any) => { if (service?.Model?.close) { await new Promise(resolve => service.Model.close(resolve)); } }) ); }); it('registered the service', () => { const service = app.service('auth-sms'); expect(service).toBeTruthy(); }); });
临时规避方案
如果赶时间不想修改业务代码,可直接修改Jest配置跳过检测,该方案不推荐长期使用,会掩盖真正的内存泄漏问题:
修改jest.config.js添加如下配置:
module.exports = { // 其他原有配置 detectOpenHandles: false, forceExit: true };
也可以直接在运行测试时添加参数:npx jest --forceExit --detectOpenHandles=false
内容的提问来源于stack exchange,提问作者Soullivaneuh
相关产品推荐
相关产品推荐

