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

fastify-cli测试环境中jwt装饰器undefined问题求助

问题描述

我用fastify-cli构建服务器应用,测试时需要生成测试用JWT,想调用fastify-jwt插件的sign方法。
用fastify start -l info ./src/app.js启动应用时一切正常,能正常访问jwt装饰器;但用node-tap执行tap "test/**/*.test.js" --reporter=list跑测试时,却报错jwt装饰器未定义,找不到问题原因。

相关代码如下:

app.js

import { dirname, join } from 'path'
import autoload from '@fastify/autoload'
import { fileURLToPath } from 'url'
import jwt from '@fastify/jwt'

export const options = {
  ignoreTrailingSlash: true,
  logger: true
}

export default async (fastify, opts) => {
  await fastify.register(jwt, {
    secret: process.env.JWT_SECRET
  })

  // autoload plugins and routes
  await fastify.register(autoload, {
    dir: join(dirname(fileURLToPath(import.meta.url)), 'plugins'),
    options: Object.assign({}, opts),
    forceESM: true,
  })

  await fastify.register(autoload, {
    dir: join(dirname(fileURLToPath(import.meta.url)), 'routes'),
    options: Object.assign({}, opts),
    forceESM: true
  })
}

helper.js

import { fileURLToPath } from 'url'
import helper from 'fastify-cli/helper.js'
import path from 'path'

// config for testing
export const config = () => {
  return {}
}

export const build = async (t) => {
  const argv = [
    path.join(path.dirname(fileURLToPath(import.meta.url)), '..', 'src', 'app.js')
  ]

  const app = await helper.build(argv, config())

  t.teardown(app.close.bind(app))

  return app
}

root.test.js

import { auth, build } from '../helper.js'
import { test } from 'tap'

test('requests the "/" route', async t => {
  t.plan(1)

  const app = await build(t)

  const token = app.jwt.sign({ ... }) //-> jwt is undefined

  const res = await app.inject({
    method: 'GET',
    url: '/'
  })

  t.equal(res.statusCode, 200, 'returns a status code of 200')
})
解决方案

1. 补全测试环境的JWT_SECRET环境变量

fastify-jwt注册时依赖process.env.JWT_SECRET,测试环境里这个变量大概率未设置,导致插件注册失败,装饰器无法生成。

可以直接在helper.js的config里添加环境变量:

export const config = () => {
  return {
    env: {
      JWT_SECRET: 'test-only-secret' // 测试专用密钥,无需复杂加密
    }
  }
}

或者在测试文件开头手动设置:

process.env.JWT_SECRET = 'test-only-secret'

2. 替换fastify-cli的helper,手动构建fastify实例

fastify-cli的helper.build有时会隐藏初始化细节,换成手动构建更可控:
修改helper.js的build函数:

import Fastify from 'fastify'
import appFactory from '../src/app.js'

export const build = async (t) => {
  // 初始化fastify实例
  const fastify = Fastify({
    ignoreTrailingSlash: true,
    logger: false // 测试时关闭日志更清爽
  })

  // 强制设置测试环境的密钥
  process.env.JWT_SECRET = 'test-only-secret'

  // 注册你的应用逻辑
  await fastify.register(appFactory)

  // 测试结束后关闭实例
  t.teardown(() => fastify.close())

  return fastify
}

这种方式绕开fastify-cli的封装,能确保插件按你的代码逻辑正常注册。

3. 验证插件注册状态(排查用)

在app.js里加一行日志,确认插件是否注册成功:

export default async (fastify, opts) => {
  await fastify.register(jwt, {
    secret: process.env.JWT_SECRET
  })
  // 打印确认信息,测试时可查看
  console.log('jwt装饰器是否存在:', !!fastify.jwt)

  // ... 其他注册逻辑
}

如果打印结果是false,那肯定是环境变量未设置导致注册失败;如果是true,再检查测试代码里的app实例是否正确获取。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 17:20:45