如何使用jest.spyOn为指定JavaScript代码片段编写测试用例?
问题描述
以下是一段包含异步函数与表单提交事件监听器的JavaScript代码片段:
async function getValue() { const firstName = document.getElementById("first_name").value; const lastName = document.getElementById("last_name").value; await saveData(new Customer(undefined, firstName, lastName)); dispatchEvent(new Event(DATA_CHANGED_EVENT)); } document.getElementById("addCustomerForm").addEventListener("submit", getValue);
现需使用jest.spyOn为其编写测试用例,具体实现方式如下:
测试用例实现方案
我们可以借助Jest的spyOn方法模拟DOM操作、异步函数调用和事件派发行为,验证getValue的逻辑是否符合预期,分步骤实现如下:
1. 初始化测试环境
Jest默认集成jsdom环境,可直接模拟浏览器DOM。测试前需先定义全局依赖并重置模拟状态:
// 模拟全局变量与函数 global.DATA_CHANGED_EVENT = 'dataChanged'; global.saveData = jest.fn().mockResolvedValue(true); global.Customer = jest.fn((id, firstName, lastName) => ({ id, firstName, lastName })); // 测试前后的DOM与模拟清理 beforeEach(() => { jest.clearAllMocks(); // 创建并挂载DOM元素 const firstNameInput = document.createElement('input'); firstNameInput.id = 'first_name'; const lastNameInput = document.createElement('input'); lastNameInput.id = 'last_name'; const form = document.createElement('form'); form.id = 'addCustomerForm'; document.body.append(firstNameInput, lastNameInput, form); // 重新引入目标模块(确保事件监听器重新绑定) require('./your-module-path'); // 替换为实际的代码文件路径 }); afterEach(() => { document.body.innerHTML = ''; });
2. 核心测试用例:验证完整流程
使用jest.spyOn监听dispatchEvent,验证表单提交后的全流程行为:
test('表单提交时应正确获取输入、调用saveData并派发事件', async () => { // 用spyOn监听document的dispatchEvent方法 const dispatchSpy = jest.spyOn(document, 'dispatchEvent').mockImplementation(() => true); // 填充输入框并触发提交事件 document.getElementById('first_name').value = 'Alice'; document.getElementById('last_name').value = 'Smith'; document.getElementById('addCustomerForm').dispatchEvent(new Event('submit')); // 等待异步操作完成 await new Promise(process.nextTick); // 验证Customer实例化参数 expect(Customer).toHaveBeenCalledWith(undefined, 'Alice', 'Smith'); // 验证saveData被正确调用 expect(saveData).toHaveBeenCalledTimes(1); expect(saveData).toHaveBeenCalledWith(expect.any(Object)); // 验证事件派发行为 expect(dispatchSpy).toHaveBeenCalledWith(expect.any(Event)); expect(dispatchSpy).toHaveBeenCalledWith(new Event(DATA_CHANGED_EVENT)); // 恢复原方法 dispatchSpy.mockRestore(); });
3. 边界场景测试:空输入值
test('输入为空时仍应执行完整流程', async () => { const dispatchSpy = jest.spyOn(document, 'dispatchEvent').mockImplementation(() => true); // 清空输入框并提交 document.getElementById('first_name').value = ''; document.getElementById('last_name').value = ''; document.getElementById('addCustomerForm').dispatchEvent(new Event('submit')); await new Promise(process.nextTick); expect(Customer).toHaveBeenCalledWith(undefined, '', ''); expect(saveData).toHaveBeenCalled(); expect(dispatchSpy).toHaveBeenCalled(); dispatchSpy.mockRestore(); });
内容的提问来源于stack exchange,提问作者adMint
相关产品推荐
相关产品推荐

