Electron环境Jest测试报错:unzipSync及fs.rm不是函数
Electron Jest测试中fflate与fs-extra函数失效问题
在Electron环境中用Jest执行单元测试时遇到两个异常:
- 调用
fflate的unzipSync时抛出错误:TypeError: (0 , _fflate.unzipSync) is not a function,该函数在生产环境运行正常,仅测试环境失效。 - 使用
fs-extra的remove方法时触发fs.rm is not a function错误,但readFile等其他方法可正常使用。所有功能在实际应用中均正常,仅Jest测试失败,询问是否需要调整测试配置。
业务代码
import { copy, emptyDir, outputFile, pathExists, readFile, remove, } from 'fs-extra'; import { IReadProfileParams } from './types'; import { join } from 'path'; import { unzipSync } from 'fflate'; async function readProfile(params: IReadProfileParams) { try { const { profilePath, tmpPath, resPath, tempResPath } = params; const profileData = await readFile(profilePath); const unzipped = unzipSync(profileData); // 复制资源文件 await emptyDir(tmpPath); const promises = []; for (const key of Object.keys(unzipped)) { if (unzipped[key].length) { const filePath = join(tmpPath, key); promises.push(outputFile(filePath, unzipped[key])); } } await Promise.all(promises); // 迁移资源目录 await copy(resPath, tempResPath, { overwrite: true }); await remove(resPath); } catch (e) { throw new Error(e); } }
jest.config.js配置
module.exports = { collectCoverageFrom: ['<rootDir>/src/renderer/src/utils/**/index.ts'], moduleNameMapper: { '@/(.*)': '<rootDir>/src/renderer/src/$1', 'src/renderer/src/constants/path.ts': '<rootDir>/mocks/func.js', }, runner: 'jest-electron/runner', testEnvironment: 'jest-electron/environment', testMatch: ['<rootDir>/src/renderer/**/*.test.ts'], setupFiles: ['./test/setup.js'], };
setup.js配置
import * as fflate from 'fflate'; const fkill = require('fkill'); const { app } = require('./electron/app'); exports.mochaGlobalSetup = async () => { await app.start(); app.browserWindow.focus(); app.browserWindow.setAlwaysOnTop(true); }; exports.mochaGlobalTeardown = async () => { if (app && app.isRunning()) { await app.stop(); } await fkill(":8238", { force:true }); };
触发fs.rm错误的简化测试代码
import { copy, emptyDir, outputFile, pathExists, readFile, remove, } from 'fs-extra'; import { IReadProfileParams } from './types'; import { join } from 'path'; import { unzipSync } from 'fflate'; async function readProfile(params: IReadProfileParams) { try { const { profilePath, tmpPath, resPath, tempResPath } = params; const profileData = await readFile(profilePath); await remove(resPath); } catch (e) { throw new Error(e); } }
解决方案
针对fflate的unzipSync失效问题
- 强制使用CommonJS版本:fflate默认提供ESM格式,Jest处理时可能存在兼容问题。在
jest.config.js的moduleNameMapper中添加映射:
moduleNameMapper: { // 保留原有配置 'fflate': '<rootDir>/node_modules/fflate/cjs/index.js' }
- 调整transform规则:如果使用
babel-jest,在jest.config.js中添加配置排除fflate的转译:
transformIgnorePatterns: ['/node_modules/(?!fflate)/']
针对fs-extra remove方法触发fs.rm错误问题
- 升级jest-electron:
fs.rm是Node.js 14.14+新增API,旧版本jest-electron的Node环境版本较低,升级至最新版可解决该问题。 - 手动Polyfill fs.rm:在
setup.js中添加兼容实现:
const fs = require('fs'); if (!fs.rm) { fs.rm = function(path, opts, callback) { if (typeof opts === 'function') { callback = opts; opts = {}; } // 模拟rm逻辑,根据需求选择unlink或rmdir fs.unlink(path, callback); }; }
- Mock remove方法:在测试文件中直接mock
fs-extra的remove方法,避免调用底层API:
jest.mock('fs-extra', () => ({ ...jest.requireActual('fs-extra'), remove: jest.fn().mockResolvedValue(undefined) }));
内容的提问来源于stack exchange,提问作者Cat Liu
相关产品推荐
相关产品推荐

