Jest中调用封装了jest.mock的公共mock函数不生效如何解决
问题根因
Jest 的 jest.mock 是编译阶段生效的语句:Jest 的 babel 插件会在代码执行前,把当前文件顶级作用域下的所有 jest.mock 语句提升到文件最顶部,早于所有 import/require 执行。你将 jest.mock 封装在 mockEndpoints 函数内部时,函数内的 jest.mock 不会被识别提升,只有运行时调用函数才会执行,此时测试文件顶部的业务模块早已加载完成,mock 自然不会生效。
可行解决方案
方案1:无函数封装的公共mock文件(最推荐)
直接在工具文件中写顶级作用域的 jest.mock 语句,不需要包裹函数:
// src/endpoints/__utils__/mockAllEndpoints.ts jest.mock('../do-log-in'); jest.mock('../get-api-key'); jest.mock('../get-rsa-key'); // 其余同类mock
测试文件中仅需在最顶部导入该文件即可生效:
// 测试文件第一行导入,确保mock早于业务模块加载 import '../endpoints/__utils__/mockAllEndpoints'; // 后续导入其他业务模块、写测试用例
方案2:全局自动mock
如果所有测试都需要这些接口mock,直接把该文件加入Jest全局启动配置即可,不需要每个测试文件单独导入:
在jest.config.js(或对应配置文件)中添加:
module.exports = { // 其余原有配置 setupFilesAfterEnv: ['<rootDir>/src/endpoints/__utils__/mockAllEndpoints.ts'] }
方案3:动态mock(仅适用于需要按需开启mock的场景)
如果部分测试需要开启这些mock、部分不需要,可使用jest.doMock配合动态加载模块实现:
// src/endpoints/__utils__/mockEndpoints.ts // 注意路径要改为相对于测试文件的路径,或者直接使用绝对路径 export function mockEndpoints() { jest.doMock('../endpoints/do-log-in'); jest.doMock('../endpoints/get-api-key'); jest.doMock('../endpoints/get-rsa-key'); }
测试文件中不能静态导入业务模块,必须在调用mockEndpoints之后再加载:
import { mockEndpoints } from '../endpoints/__utils__/mockEndpoints'; // 先调用mock mockEndpoints(); // 再动态加载需要用到这些接口的业务模块 const businessModule = require('../business-logic'); describe('test cases', () => { // 测试用例使用加载后的businessModule即可 })
内容的提问来源于stack exchange,提问作者Tim
相关产品推荐
相关产品推荐

