You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 21:25:39