Next.js配置jest-fetch-mock运行测试报TextEncoder未定义错误
问题原因
之前尝试从util引入TextEncoder挂载全局不生效,核心原因是挂载时机过晚:setupFilesAfterEnv里的脚本会在Jest测试框架、Next.js测试配置加载完成后才执行,而Next.js内部模块、jsdom环境初始化阶段就已经调用了TextEncoder,此时全局还没有注入对应API,就会抛出引用错误。
可行解决方案
方案1:提前注入全局polyfill(优先使用,适配90%以上场景)
- 在项目根目录新建
jest.polyfills.js文件,写入以下内容:
/* eslint-disable @typescript-eslint/no-var-requires */ const { TextEncoder, TextDecoder } = require('util') // 同时挂载到全局对象,覆盖Node环境与jsdom window上下文 Object.assign(globalThis, { TextEncoder, TextDecoder, // 若后续抛出Request/Response/Headers未定义错误,可保留以下配置(Node 18+ 内置支持) Request, Response, Headers })
- 修改
jest.config.js中的配置,将polyfill加入setupFiles数组(该配置下的脚本执行时机早于setupFilesAfterEnv,会在测试环境初始化前完成注入):
const customJestConfig = { // 新增该行,polyfill必须放在最前 setupFiles: ['<rootDir>/jest.polyfills.js'], setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'], moduleDirectories: ['<rootDir>/node_modules', '<rootDir>/src', '<rootDir>/pages'], testEnvironment: 'jest-environment-jsdom', testPathIgnorePatterns: [ '<rootDir>/.next/', '<rootDir>/node_modules/', '<rootDir>/coverage', '<rootDir>/dist' ], moduleNameMapper: { '^@/(.*)$': '<rootDir>/$1' }, resolver: '<rootDir>/.jest/resolver.js' }
方案2:自定义jsdom测试环境(方案1无效时使用)
如果方案1仍报错,说明jsdom环境实例化阶段就需要调用TextEncoder,此时通过自定义测试环境在构造阶段注入API即可:
- 在项目根目录新建
jest.environment.js文件,写入以下内容:
/* eslint-disable @typescript-eslint/no-var-requires */ const JsdomEnvironment = require('jest-environment-jsdom') const { TextEncoder, TextDecoder } = require('util') module.exports = class CustomTestEnvironment extends JsdomEnvironment { constructor(config, context) { super(config, context) // 环境实例化阶段直接挂载API到jsdom全局上下文 this.global.TextEncoder = TextEncoder this.global.TextDecoder = TextDecoder this.global.Request = Request this.global.Response = Response this.global.Headers = Headers } }
- 修改
jest.config.js中的testEnvironment配置,指向自定义环境文件:
const customJestConfig = { setupFilesAfterEnv: ['<rootDir>/jest.setup.ts'], // 替换原有testEnvironment配置 testEnvironment: '<rootDir>/jest.environment.js', // 其余配置保持不变 moduleDirectories: ['<rootDir>/node_modules', '<rootDir>/src', '<rootDir>/pages'], testPathIgnorePatterns: [ '<rootDir>/.next/', '<rootDir>/node_modules/', '<rootDir>/coverage', '<rootDir>/dist' ], moduleNameMapper: { '^@/(.*)$': '<rootDir>/$1' }, resolver: '<rootDir>/.jest/resolver.js' }
兼容处理
如果你的Node.js版本低于18,从util引入的API可能存在兼容问题,可以安装text-encoding包做polyfill,将上述代码中引入util的部分替换为:
const { TextEncoder, TextDecoder } = require('text-encoding')
注意不要在jest.setup.ts中重复覆盖TextEncoder、TextDecoder全局变量,避免产生冲突。
内容的提问来源于stack exchange,提问作者rottitime
相关产品推荐
相关产品推荐

