NestJS搭配SuperTest+Jest测试运行后不退出,如何存储接口返回值供后续用例使用
问题根源
- 测试执行完成后,你初始化的Nest应用实例没有被手动关闭,端口监听、数据库连接等后台资源仍处于占用状态,导致Jest检测到活跃的异步句柄无法退出
- 你直接返回request调用链能正常退出是因为supertest内部会在Promise完成后自动释放单次请求的相关资源,但这种写法没法捕获返回值存储token/id,不满足你的业务需求
规范解决方案
1. 测试前后正确管理Nest应用生命周期
在测试文件的beforeAll钩子中初始化Nest应用,在afterAll钩子中手动关闭应用、销毁相关资源,示例代码如下:
import { Test } from '@nestjs/testing'; import { AppModule } from '../src/app.module'; import * as request from 'supertest'; describe('Auth API test', () => { let app; let token; // 全局存储需要复用的token/id beforeAll(async () => { // 初始化测试模块 const moduleFixture = await Test.createTestingModule({ imports: [AppModule], }).compile(); app = moduleFixture.createNestApplication(); await app.init(); }); // 测试跑完后手动关闭应用释放资源 afterAll(async () => { await app.close(); }); it('/auth/register (POST)', async () => { const res = await request(app.getHttpServer()) .post('/api/auth/register') .send({username: "Zoe"}) .expect(201); token = res.body.token; // 正常获取返回值即可 }); // 后续测试用例可以直接复用存储的token it('/auth/profile (GET)', async () => { const res = await request(app.getHttpServer()) .get('/api/auth/profile') .set('Authorization', `Bearer ${token}`) .expect(200); // 此处编写断言逻辑 }); })
2. 额外资源释放补充
如果你的应用里有数据库连接、Redis连接等长连接资源,在afterAll钩子中也要同步关闭,比如使用TypeORM的场景可以加:
afterAll(async () => { await app.get(Connection).close(); await app.close(); })
3. 问题定位补充配置
如果还有偶现的退出问题,可以在jest配置中加detectOpenHandles: true定位具体未释放的句柄,不建议直接使用forceExit配置,强制退出会掩盖真实的资源泄漏问题。
内容的提问来源于stack exchange,提问作者Lars Flieger
相关产品推荐
相关产品推荐

