You need to enable JavaScript to run this app. 如何在Jest自定义环境文件中Mock服务端路由依赖的中间件函数
优惠活动
大模型
产品
解决方案
定价
更多

如何在Jest自定义环境文件中Mock服务端路由依赖的中间件函数

问题核心原因
  • 自定义NodeEnvironment运行在jest主进程上下文,未注入jest全局对象,因此直接调用jest.mock会报错。
  • 服务实例在setup阶段已经完成初始化,所有中间件的引用已经被加载固定,测试文件执行时再调用jest.mock无法替换已经存在的中间件实例,因此Mock不会生效。
可行实现方案

方案1:全局统一Mock(所有测试共用相同Mock实现)

适合所有测试都需要同一套Mock中间件的场景,直接在自定义环境中通过改写require缓存实现Mock,无需使用jest.mock:

const NodeEnvironment = require('jest-environment-node')
const supertest = require('supertest')

// 先改写需要Mock的中间件的模块缓存,再加载server
// 示例:Mock src/middlewares/auth.js 中间件
const mockAuthMiddleware = async (ctx, next) => {
  ctx.state.user = { id: 1, role: 'admin' } // 你的Mock逻辑
  await next()
}
require.cache[require.resolve('../src/middlewares/auth.js')] = {
  exports: mockAuthMiddleware
}

// 此时加载的server会自动使用上面Mock的中间件
const { app, init } = require('../src/server')

class ServerEnvironment extends NodeEnvironment {
  constructor(config, context) {
    super(config, context)
    this.testPath = context.testPath
  }

  async setup() {
    await init
    this.server = app.listen()
    this.api = supertest(this.server)
    this.global.api = this.api
  }

  async teardown() {
    this.server.close()
  }
}

module.exports = ServerEnvironment

方案2:单测试文件定制Mock(不同测试可使用不同Mock实现)

适合不同测试需要不同Mock逻辑的场景,给中间件增加运行时代理层即可实现动态切换:

  1. 调整服务端中间件注册逻辑,增加全局Mock兜底:
// src/server.js 中修改需要支持Mock的中间件注册部分
const authMiddleware = require('./middlewares/auth')
// 增加全局Mock判断,存在则优先使用Mock实现
const useMock = global.__SERVER_MOCKS__?.auth ?? authMiddleware
app.use(useMock)
  1. 修改自定义环境,暴露全局Mock设置方法:
class ServerEnvironment extends NodeEnvironment {
  constructor(config, context) {
    super(config, context)
    this.testPath = context.testPath
  }

  async setup() {
    await init
    // 初始化全局Mock存储对象
    this.global.__SERVER_MOCKS__ = {}
    // 暴露设置Mock的全局方法
    this.global.setServerMock = (middlewareName, mockImpl) => {
      this.global.__SERVER_MOCKS__[middlewareName] = mockImpl
    }
    // 暴露清除Mock的全局方法
    this.global.clearServerMocks = () => {
      this.global.__SERVER_MOCKS__ = {}
    }
    this.server = app.listen()
    this.api = supertest(this.server)
    this.global.api = this.api
  }

  async teardown() {
    this.server.close()
  }
}
  1. 在测试文件中直接调用全局方法设置Mock即可生效:
// 某测试文件示例
describe('测试需要Mock鉴权的接口', () => {
  beforeAll(() => {
    // 自定义当前测试需要的Mock逻辑
    setServerMock('auth', async (ctx, next) => {
      ctx.state.user = { id: 2, role: 'guest' }
      await next()
    })
  })

  afterAll(() => {
    clearServerMocks()
  })

  test('测试游客权限接口', async () => {
    const res = await api.get('/guest/api')
    expect(res.statusCode).toBe(200)
  })
})

注:该方案利用中间件每次请求触发时才执行的特性,无需重启服务即可动态切换Mock实现,性能开销极低。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.13 12:30:02