You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jest v27升级后FeathersJS NeDB服务报FSREQCALLBACK警告如何解决

解决方案

根本原因

Jest v27 版本默认开启了未关闭句柄检测逻辑,你项目中使用的NeDB数据库在开启autoload持久化存储时,会生成常驻的文件系统操作句柄,测试运行结束后没有主动释放,就会触发该警告。

推荐根治方案

方案1:测试环境改用内存模式NeDB

测试环境下不需要持久化存储数据,直接将NeDB改为内存运行模式即可完全消除文件句柄问题,同时还能提升测试运行速度。
在测试环境的Feathers配置中添加:

// 测试环境加载配置时添加
app.set('nedb', {
  inMemoryOnly: true,
  autoload: true
});

方案2:测试前后主动清理资源

如果你需要在测试中使用持久化NeDB,可通过以下步骤处理:

  1. 修改src/app.ts的导出逻辑,从导出单例app改为导出app工厂函数,避免跨测试用例的状态污染:
// src/app.ts 修改前
const app = feathers();
// 所有配置逻辑
export default app;

// 修改后
export default () => {
  const app = feathers();
  // 原来的所有配置逻辑原样移入
  return app;
}
  1. 调整测试用例代码,测试前创建新的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 10:12:01