如何为接收argv的命令行write函数编写测试并实现全覆盖?
解决Jest测试write函数时的进程异常问题并实现100%覆盖率
问题根源
你遇到的jest worker encountered 4 child process exceptions错误,本质是write函数里直接调用了process.exit()——Jest的测试worker进程被强制终止,多次重试后触发了上限。另外未隔离process.argv修改、未mock文件读写副作用,也会导致测试不稳定。
分步解决方案
1. 拆分业务逻辑与进程退出逻辑
把process.exit()从write函数中剥离,移到脚本入口文件,让write专注于业务逻辑,抛出错误而非直接终止进程:
// src/write.js import fs from 'fs'; import { figmaToChakra } from './figmaToChakra.js'; export function write() { // 从命令行参数获取路径 const [inputPath, outputPath] = process.argv.slice(2); // 参数校验 if (!inputPath || !outputPath) { throw new Error('请传入输入文件路径和输出文件路径'); } try { // 读取输入文件 const rawData = fs.readFileSync(inputPath, 'utf8'); // 转换数据 const transformedData = figmaToChakra(rawData); // 写入输出文件 fs.writeFileSync(outputPath, JSON.stringify(transformedData, null, 2)); return transformedData; } catch (err) { throw new Error(`处理失败: ${err.message}`); } } // bin/figma-to-chakra.js(脚本入口) #!/usr/bin/env node import { write } from '../src/write.js'; write() .then(() => { console.log('转换完成'); process.exit(0); }) .catch((err) => { console.error(err); process.exit(1); });
2. Mock文件系统与依赖
用Jest mockfs模块和figmaToChakra函数,避免实际读写文件,隔离外部依赖:
// __tests__/write.test.js import { write } from '../src/write.js'; import fs from 'fs'; import { figmaToChakra } from '../src/figmaToChakra.js'; // Mock文件系统 jest.mock('fs'); // Mock转换函数 jest.mock('../src/figmaToChakra.js', () => ({ figmaToChakra: jest.fn(() => ({ theme: 'mock-chakra-theme' })) }));
3. 隔离process.argv修改
在每个测试用例前后保存、恢复原始process.argv,避免测试间互相影响:
describe('write函数测试', () => { const originalArgv = [...process.argv]; beforeEach(() => { jest.clearAllMocks(); // 恢复原始命令行参数 process.argv = [...originalArgv]; });
4. 编写全分支测试用例
覆盖所有代码路径,确保100%覆盖率:
// 测试正常流程 test('成功读取、转换并写入文件', () => { // 设置测试用命令行参数 process.argv.push('./input.json', './output.json'); // Mock读文件返回值 fs.readFileSync.mockReturnValue(JSON.stringify({ figmaTheme: 'test-data' })); const result = write(); expect(fs.readFileSync).toHaveBeenCalledWith('./input.json', 'utf8'); expect(figmaToChakra).toHaveBeenCalledWith(JSON.stringify({ figmaTheme: 'test-data' })); expect(fs.writeFileSync).toHaveBeenCalledWith( './output.json', JSON.stringify({ theme: 'mock-chakra-theme' }, null, 2) ); expect(result).toEqual({ theme: 'mock-chakra-theme' }); }); // 测试参数缺失 test('未传入路径时抛出错误', () => { expect(() => write()).toThrow('请传入输入文件路径和输出文件路径'); }); // 测试输入文件不存在 test('输入文件不存在时抛出错误', () => { process.argv.push('./non-exist.json', './output.json'); fs.readFileSync.mockImplementation(() => { throw new Error('ENOENT: 文件不存在'); }); expect(() => write()).toThrow('处理失败: ENOENT: 文件不存在'); }); // 测试转换函数失败 test('转换数据失败时抛出错误', () => { process.argv.push('./input.json', './output.json'); fs.readFileSync.mockReturnValue('invalid-data'); figmaToChakra.mockImplementation(() => { throw new Error('数据格式错误'); }); expect(() => write()).toThrow('处理失败: 数据格式错误'); }); // 测试写入文件失败 test('写入输出文件失败时抛出错误', () => { process.argv.push('./input.json', './output.json'); fs.readFileSync.mockReturnValue(JSON.stringify({ figmaTheme: 'test-data' })); fs.writeFileSync.mockImplementation(() => { throw new Error('权限不足'); }); expect(() => write()).toThrow('处理失败: 权限不足'); }); });
验证与运行
执行测试命令:
jest __tests__/write.test.js --coverage
此时测试不会再触发进程退出异常,且能覆盖所有代码分支,达到100%覆盖率。
内容的提问来源于stack exchange,提问作者Hasan
相关产品推荐
相关产品推荐

