使用Middy时单元测试Handler调用,Mock后中间件仍执行如何解决
错误原因
- 你在
jest.mock的工厂函数中调用了jest.requireActual加载原模块,此时原模块内middy(handler).use(ssm())的初始化逻辑会直接执行,SSM中间件已经挂载到原函数实例上。虽然你后续尝试将导出的makeThirdPartyServiceRequest替换为Jest模拟函数,但如果对象引用替换不彻底,测试时仍然会调用到挂载了中间件的原Middy实例。 - 保留原模块所有导出再覆盖单个属性的写法,在部分模块导入场景下可能出现引用残留,导致模拟函数未生效。
解决方案
方案1:直接模拟目标函数(推荐)
不需要加载原模块逻辑,直接导出模拟函数即可,修改mock代码如下:
jest.mock('../src/thirdPartyService', () => ({ __esModule: true, default: { // 如果需要保留原模块的其他导出可以保留下面这行,否则建议删除,避免触发原模块初始化逻辑 // ...(jest.requireActual('../src/thirdPartyService') as { default: {} }).default, makeThirdPartyServiceRequest: jest.fn() } })) // import 语句必须放在 jest.mock 之后(Jest会自动提升jest.mock调用到所有导入前,手动按顺序写更易维护) import thirdPartyService from '../src/thirdPartyService' import { mocked } from 'jest-mock'
如果修改后还是触发中间件,可以加一行日志验证模拟是否生效:
it('should makeThirdPartyServiceRequest', async () => { // 输出如果是 [Function: mockConstructor] 说明模拟生效,如果是Middy实例说明模拟未生效 console.log(thirdPartyService.makeThirdPartyServiceRequest) // 剩余测试逻辑 })
如果模拟未生效,检查两点:
- mock中的文件相对路径是否和测试文件到目标模块的路径完全一致,不要写错路径
- 原模块的导出方式是否和mock匹配:如果原模块是
export const makeThirdPartyServiceRequest = xxx命名导出,mock结构不要放在default属性下
方案2:模拟SSM中间件(适用于测试原函数业务逻辑的场景)
如果你不需要mock整个请求函数,只是想跳过SSM中间件的执行,可以直接mock SSM中间件:
jest.mock('@middy/ssm', () => jest.fn(() => ({ before: jest.fn((handler, next) => next()) // 直接跳过SSM参数拉取逻辑,进入业务代码 })))
注:测试代码中的多余注释
// })是笔误,删除即可,不影响逻辑运行。
内容的提问来源于stack exchange,提问作者Muhammad Ali Nazar
相关产品推荐
相关产品推荐

