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

Jest运行NestJS e2e测试时Prisma与PostgreSQL连接过多如何解决

问题原因

你当前的测试代码存在两个致命问题,直接导致数据库连接泄漏:

  • 每个beforeEach钩子中手动new PrismaService()创建的实例,和测试模块编译时自动初始化的PrismaService是完全独立的两个对象。你在afterEach中调用$disconnect()释放的只是自己手动创建的实例,真正被业务逻辑调用、由Nest依赖注入容器管理的Prisma实例从来没有被断开连接。
  • 每个测试用例执行完成后没有调用app.close()销毁应用实例,模块持有的数据库连接、上下文资源都没有被正常回收。每个用例重建一次应用就会新建一组数据库连接,累计下来很快就会触发PostgreSQL的连接数上限。
修复方案

推荐写法:单测试套件共享应用实例

端到端测试不需要每个用例都重建整个Nest应用,整个describe块只初始化一次应用和Prisma连接即可,用例之间通过清理业务数据实现隔离,性能更好也不会产生连接泄漏。
修正后的测试代码:

import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import { AppModule } from '../src/app.module';
import { PrismaService } from '../src/prisma.service';

describe('Users', () => {
  let app: INestApplication;
  const gql = '/graphql';
  let prisma: PrismaService;

  beforeAll(async () => {
    const moduleFixture: TestingModule = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = moduleFixture.createNestApplication();
    // 从Nest依赖注入容器获取已经完成初始化的PrismaService实例,禁止手动new
    prisma = app.get(PrismaService);
    await app.init();
  });

  afterAll(async () => {
    // 销毁顺序不能错:先关闭应用释放所有资源,再断开Prisma连接
    await app.close();
    await prisma.$disconnect();
  });

  // 用例之间的数据清理放在beforeEach,不需要重建连接
  beforeEach(async () => {
    // 按需清理测试表数据,避免用例间状态污染,例如:
    // await prisma.user.deleteMany();
  });

  it('Query - Users', async () => {
    // 测试逻辑直接复用上面初始化的prisma实例即可
  });
});

强隔离场景写法(不推荐,性能较低)

如果你确实需要每个用例都使用完全独立的应用上下文,必须保证每个用例执行完后正确销毁所有资源,且全程不要手动实例化PrismaService:

beforeEach(async () => {
  const moduleFixture: TestingModule = await Test.createTestingModule({
    imports: [AppModule],
  }).compile();

  app = moduleFixture.createNestApplication();
  prisma = app.get(PrismaService);
  await app.init();
});

afterEach(async () => {
  // 必须先关闭应用,再断开Prisma连接,不能漏掉app.close()
  await app.close();
  await prisma.$disconnect();
});
额外优化配置
  • 测试环境下调小Prisma连接池大小,串行测试场景下连接池最大连接数设为1就足够使用,从根源减少连接占用。修改PrismaService构造函数:
import { INestApplication, Injectable, OnModuleInit } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';

@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
  constructor() {
    super({
      ...(process.env.NODE_ENV === 'test' ? {
        connectionLimit: 1,
        log: ['error'],
      } : {})
    });
  }

  async onModuleInit() {
    await this.$connect();
  }

  async enableShutdownHooks(app: INestApplication) {
    this.$on('beforeExit', async () => {
      await app.close();
    });
  }
}
  • 在e2e测试脚本中添加--forceExit参数,避免测试执行完成后还有挂起的连接占用进程导致资源泄漏:
{
  "scripts": {
    "test:e2e": "jest --config ./test/jest-e2e.json --forceExit"
  }
}

核心注意点:所有PrismaService实例都必须从Nest依赖注入容器获取,不要在测试代码中手动调用new创建实例,重复实例化PrismaClient是连接数暴涨的最常见原因。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.13 16:15:54