GitHub Actions CI中Jest测试EjsAdapter开放句柄问题解决
解决EjsAdapter导致Jest测试无法终止的开放句柄问题
从错误栈来看,问题根源是@nestjs-modules/mailer的EjsAdapter依赖的@css-inline/css-inline模块中存在未关闭的CustomGC开放句柄,导致Jest无法正常退出。以下是几种可行的解决方案:
手动清理CustomGC句柄
在全局测试初始化文件(比如jest.setup.ts)或单个测试文件中添加清理逻辑,手动销毁CustomGC实例:import { CustomGC } from '@css-inline/css-inline'; afterAll(() => { // 检查并销毁CustomGC实例 if (CustomGC?.instance?.destroy) { CustomGC.instance.destroy(); } });记得在
jest.config.js中配置该初始化文件:module.exports = { setupFilesAfterEnv: ['./jest.setup.ts'], // 其他配置... };强制Jest退出(临时应急方案)
如果手动清理无效,可以在Jest命令中添加--forceExit参数,强制Jest忽略开放句柄并退出:// package.json中的test脚本 "test": "jest --detectOpenHandles --forceExit"注意:这是临时方案,仅用于紧急情况下让流水线正常结束,不建议长期依赖。
自定义Ejs适配器(长期根治方案)
绕过官方EjsAdapter中依赖的css-inline模块,自己实现一个轻量的Ejs适配器:import { Injectable } from '@nestjs/common'; import { MailerOptions, TemplateAdapter } from '@nestjs-modules/mailer'; import * as ejs from 'ejs'; @Injectable() export class CustomEjsAdapter implements TemplateAdapter { compile(template: string, _options: MailerOptions['template']): (context: any) => Promise<string> { return async (context) => ejs.render(template, context); } }然后在MailerModule中替换适配器:
MailerModule.forRootAsync({ useFactory: (configService: ConfigService) => ({ transport: configService.get('mail.transport'), template: { adapter: new CustomEjsAdapter(), // 使用自定义适配器 options: { strict: true } } }), inject: [ConfigService] })升级依赖版本
检查@nestjs-modules/mailer和@css-inline/css-inline的最新稳定版,看是否已修复该开放句柄问题,执行升级命令:npm update @nestjs-modules/mailer @css-inline/css-inline
内容的提问来源于stack exchange,提问作者rrrokhtar
相关产品推荐
相关产品推荐

