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

Fastify项目Jest测试失败:default root route报错求助

问题

为Fastify项目编写Jest测试时执行失败,报错提示进程无法优雅退出,测试代码如下:

测试文件 root.test.ts

import { build } from '../helper'

const app = build()

test('default root route', async () => {
  const res = await app.inject({
    url: '/'
  })
  expect(res.json()).toEqual({ root: true })
})

辅助文件 helper.ts

import Fastify from "fastify"
import fp from "fastify-plugin"
import App from "../src/app"

export function build() {
  const app = Fastify()

  beforeAll(async () => {
    void app.register(fp(App))
    await app.ready()
  })

  afterAll(() => app.close())

  return app
}

控制台错误信息

FAIL  test/routes/root.test.ts (8.547 s)
  ● default root route




A worker process has failed to exit gracefully and has been force exited. This is likely caused by tests leaking due to improper teardown. Try running with --detectOpenHandles to find leaks. Active timers can also cause this, ensure that .unref() was called on them.

问题根源

  1. Jest生命周期钩子位置错误:beforeAll/afterAll是Jest的全局测试钩子,必须放在测试文件的顶级作用域或describe块内,不能放在普通函数(比如build)内部。你之前的写法中,Jest完全不会执行build函数里的钩子。
  2. Fastify实例未正确初始化:因为beforeAll没执行,Fastify实例没有注册业务插件,也没完成ready初始化,导致inject请求无法正常处理。
  3. 资源未正确释放:afterAll没执行,Fastify的内部资源(如定时器、连接)未关闭,导致Node.js进程无法优雅退出,触发强制退出报错。

修复方案

步骤1:修改helper.ts,移除内部的生命周期钩子,改为返回初始化完成的Fastify实例

import Fastify from "fastify"
import fp from "fastify-plugin"
import App from "../src/app"

// 改为异步函数,确保实例初始化完成后再返回
export async function build() {
  const app = Fastify()
  // 注册插件并等待初始化完成
  await app.register(fp(App))
  await app.ready()
  return app
}

步骤2:在测试文件中添加顶级作用域的生命周期钩子,处理实例的启动与关闭

import { build } from '../helper'

let app: Awaited<ReturnType<typeof build>>

// 测试前初始化Fastify实例
beforeAll(async () => {
  app = await build()
})

// 测试后关闭实例释放资源
afterAll(async () => {
  await app.close()
})

test('default root route', async () => {
  const res = await app.inject({
    url: '/'
  })
  expect(res.json()).toEqual({ root: true })
})

额外说明

  • 如果有多个测试文件需要复用Fastify实例的初始化逻辑,可以将启动/关闭逻辑放到Jest的全局配置文件(如setupFilesAfterEnv指定的文件)中,避免重复代码。
  • 若仍出现资源泄漏问题,可执行jest --detectOpenHandles命令定位未关闭的资源(如数据库连接、定时器)。

内容的提问来源于stack exchange,提问作者Some Noob Student

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 15:50:27