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

Nuxt 3集成测试中如何正确打桩服务端auth中间件

Nuxt服务端认证中间件集成测试打桩实现方案

核心失效原因

你之前尝试的两种方案不生效,本质是因为Nuxt(Nitro)启动时会自动扫描server/middleware目录,把所有中间件提前注册到请求处理链中,初始化完成后再修改配置指向、或者在测试用例里调用vi.mock(),都没法替换已经注册完成的原始中间件逻辑。


可落地方案

方案1:高优先级Nitro插件覆写上下文(推荐,无业务代码侵入)

不需要修改原始认证中间件代码,通过测试环境加载优先级更高的Nitro插件,直接覆写请求上下文中的auth字段,绕开原始AD JWT校验逻辑:

  1. 新建测试专用mock文件tests/mocks/auth-mock.ts,写入以下逻辑:
import { ref } from 'vue'
import type { Ref } from '@vue/runtime-dom'

const NOT_LOGGED_IN = null
export const isLoggedIn: Ref<{ email: string, name: string } | null> = ref(NOT_LOGGED_IN)

export const useAuthUserMock = () => ({
  resetAuthMockUser: () => {
    isLoggedIn.value = NOT_LOGGED_IN
  },
  setAuthMockUser: (email = 'user.mock@email.com', name = 'User Mock') => {
    isLoggedIn.value = { email, name }
  }
})

export default defineNitroPlugin((nitroApp) => {
  // 注册请求钩子,每个请求进入时赋值auth上下文
  nitroApp.hooks.hook('request', (event) => {
    // 如果原始中间件会在无JWT时直接抛401,把钩子改成'request:early'提前执行即可
    event.context.auth = isLoggedIn.value
  })
})
  1. 在测试配置中引入该插件,如果你用@nuxt/test-utils做集成测试,直接在测试的setup配置中添加Nitro插件配置即可,测试环境下插件会自动加载。

方案2:Vitest路径别名强制替换(适配所有场景)

如果插件方案不适用,可以直接在Vitest配置层把原始中间件的引用路径映射到mock文件,从模块解析层面替换原始逻辑:

  1. 把你写的打桩版中间件代码存到tests/mocks/auth-middleware-stub.ts
  2. 修改vitest.config.ts,添加路径别名规则:
import { defineConfig } from 'vitest/config'
import { fileURLToPath } from 'node:url'

export default defineConfig({
  resolve: {
    alias: {
      // 把原始中间件路径直接映射到mock文件
      '~/server/middleware/auth': fileURLToPath(new URL('./tests/mocks/auth-middleware-stub.ts', import.meta.url))
    }
  },
  // 其他原有测试配置不变
})

这个方案会在模块加载阶段直接替换所有对原始auth中间件的引用,不会出现mock不生效的问题。


测试用例写法参考

用例执行前记得重置登录状态,避免多用例之间状态污染:

// 导入mock状态控制方法
import { useAuthUserMock } from '~/tests/mocks/auth-mock'

describe('受保护路由集成测试', () => {
  const { resetAuthMockUser, setAuthMockUser } = useAuthUserMock()

  beforeEach(() => {
    resetAuthMockUser()
  })

  it('未登录状态访问返回预期错误码', async () => {
    const response = await fetch('/api/your-protected-route')
    expect(response.status).toBe(401)
    // 其他响应校验逻辑
  })

  it('登录状态访问正常返回结果、数据库更新符合预期', async () => {
    // 先设置登录态
    setAuthMockUser('test@company.com', '测试账号')
    const response = await fetch('/api/your-protected-route', {
      method: 'POST',
      body: JSON.stringify({ test: 'data' })
    })
    expect(response.status).toBe(200)
    // 后续校验响应内容、数据库字段逻辑
  })
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 14:03:19