如何使用Jest模拟块级作用域变量?测试含块级变量的方法
Jest测试含块级作用域变量代码的正确实践
不需要为了测试修改内部变量的作用域——测试的核心是验证函数的输入输出、依赖调用和副作用,而非直接访问内部块级变量。针对你提供的downloadAttachment方法,我们可以通过模拟依赖、断言关键行为来覆盖包括for循环在内的所有逻辑。
先贴出你的示例代码(附中文逻辑注释):
downloadAttachment(attachment: Attachment) { // 解码base64格式的附件内容 const byteCharacters = window.atob(attachment.attachment); const byteNumbers = new Array(byteCharacters.length); // 遍历字符,将每个字符转为对应ASCII码值 for (let i = 0; i < byteCharacters.length; i++) { byteNumbers[i] = byteCharacters.charCodeAt(i); } // 将码值数组转为Uint8Array const byteArray = new Uint8Array(byteNumbers); // 生成JPG格式的Blob对象 const blob = new Blob([byteArray], { type: 'image/jpeg' }); // 触发文件下载 saveAs(blob, 'attachment'); }
具体测试步骤
- 模拟全局依赖:用Jest的mock函数替换
window.atob和saveAs,方便控制返回值、断言调用行为。 - 构造可控输入:生成包含已知base64字符串的
Attachment对象,确保能预知解码后的字符内容。 - 断言关键逻辑:通过验证最终生成的Blob内容、
saveAs的调用参数,间接确认for循环的处理逻辑正确。
完整测试代码示例
import { saveAs } from 'file-saver'; import { downloadAttachment } from './your-module-path'; // 模拟saveAs函数 jest.mock('file-saver', () => ({ saveAs: jest.fn() })); describe('downloadAttachment', () => { beforeEach(() => { // 每次测试前重置mock状态 jest.clearAllMocks(); // 模拟window.atob返回固定字符串,方便后续验证编码转换 window.atob = jest.fn(() => "ABC"); }); it('应正确解码base64并触发下载', () => { // 构造测试用Attachment对象,"ABC"对应的base64编码为QUJD const testAttachment = { attachment: 'QUJD' }; // 调用目标函数 downloadAttachment(testAttachment as Attachment); // 验证atob是否被传入正确的base64参数 expect(window.atob).toHaveBeenCalledWith('QUJD'); // 验证saveAs的调用参数 const mockSaveAs = saveAs as jest.Mock; expect(mockSaveAs).toHaveBeenCalledWith(expect.any(Blob), 'attachment'); // 读取Blob内容,验证for循环的编码转换逻辑是否正确 const blob = mockSaveAs.mock.calls[0][0] as Blob; return new Promise((resolve) => { const reader = new FileReader(); reader.onload = () => { const uint8Array = new Uint8Array(reader.result as ArrayBuffer); // "ABC"对应的ASCII码为65、66、67 expect(uint8Array).toEqual(new Uint8Array([65, 66, 67])); resolve(); }; reader.readAsArrayBuffer(blob); }); }); it('应正确处理空内容的附件', () => { window.atob = jest.fn(() => ""); const testAttachment = { attachment: '' }; downloadAttachment(testAttachment as Attachment); const mockSaveAs = saveAs as jest.Mock; const blob = mockSaveAs.mock.calls[0][0] as Blob; expect(blob.size).toBe(0); }); });
核心思路说明
- 无需访问
byteCharacters、byteNumbers等内部变量,通过控制输入、验证最终输出和副作用即可覆盖所有逻辑,包括for循环的遍历转换。 - 模拟依赖能隔离外部环境影响,让测试更稳定、执行更快。
- 若要测试边界场景(如空字符串、特殊字符),只需构造对应的base64输入,复用上述验证逻辑即可。
内容的提问来源于stack exchange,提问作者fadingbeat
相关产品推荐
相关产品推荐

