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

Jest运行Apollo Server测试引入外部typeDefs出现内存泄漏问题

问题诱因与解决方案

可能的诱因

  • Jest 模块缓存机制:Jest 默认会缓存所有导入的外部模块,抽离到单独文件的typeDefs属于被缓存的模块引用,当 Apollo Server 实例持有该引用时,如果测试结束后实例没有被正确销毁,缓存模块与 Apollo 实例会形成互相持有的引用链,无法被 GC 回收,最终产生内存泄漏。当typeDefs写在同一文件时,属于文件内局部变量,测试结束后作用域销毁时更容易被回收,因此不会触发泄漏检测。
  • Apollo Server 实例未正确清理:如果在模块顶层直接初始化 Apollo Server 实例,而非在每个测试用例生命周期内创建/销毁,实例会在全量测试运行期间持续存在,结合外部导入的缓存typeDefs引用,内存占用会随测试用例增加持续累积。
  • GraphQL Schema 隐式缓存:Apollo Server 会自动将传入的typeDefs编译为 GraphQLSchema 对象,如果外部导入的typeDefs引用不变,编译后的 Schema 可能会被隐式缓存并与 Apollo 实例绑定,无法正常释放。

问题归属

该问题不属于单一组件的Bug,是 Jest 模块缓存机制、Apollo Server 实例清理逻辑、测试代码写法三者共同作用的结果。

解决方案

  1. 调整测试服务实例化逻辑,不要在模块顶层直接导出 Apollo Server 实例,改为导出工厂函数,配合测试生命周期主动创建/销毁实例:
// 测试服务文件写法
import { typeDefs } from './typeDefs';
const resolvers = {
  // resolver 逻辑
}

export const createTestServer = () => {
  return new ApolloServer({
    typeDefs,
    resolvers,
    // 其他配置项
  });
};

// 测试用例写法
describe('业务测试用例集', () => {
  let testServer;
  beforeEach(async () => {
    testServer = createTestServer();
    await testServer.start();
  });
  afterEach(async () => {
    await testServer.stop();
  });

  // 具体测试用例逻辑
});
  1. 清空 Jest 模块缓存,在测试文件顶部添加jest.resetModules()配置,或者在jest.config.js中全局配置resetModules: true,避免旧的typeDefs引用被持续持有:
// 测试文件顶部添加
jest.resetModules();
import { typeDefs } from './typeDefs';
  1. 切断引用关联,传入typeDefs时做浅拷贝,避免直接使用缓存模块的原始引用:
// 如果typeDefs是对象写法
new ApolloServer({
  typeDefs: { ...typeDefs },
  resolvers
});
// 如果typeDefs是SDL字符串写法
new ApolloServer({
  typeDefs: `${typeDefs}`,
  resolvers
});
  1. 调整 Jest 运行参数,添加--logHeapUsage打印内存占用变化辅助排查,或者添加--maxWorkers=1关闭多进程运行,避免多进程干扰泄漏检测结果。

内容的提问来源于stack exchange,提问作者jsem

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 13:21:04