Jest单元测试addEventListener方法失败,点击未触发createBlob求助
问题分析与修复方案
你的测试失败主要有以下几个核心问题,对应修复方案如下:
1. DOM查询方法Mock不匹配
原代码中getButtons使用document.querySelectorAll(".next")获取按钮(返回NodeList),但你的测试Mock的是document.querySelector(返回单个元素),导致nextClicked是空的NodeList,直接跳过了事件监听的添加逻辑。
2. Mock按钮缺少必要方法
原代码会检查按钮的listener属性,且绑定事件后会设置该属性,但你的Mock按钮没有实现getAttribute和setAttribute方法,导致条件nextClicked[0]?.getAttribute("listener") !== "true"不成立,无法进入事件绑定分支。
3. createBlob的Spy对象错误
假设createBlob是与setEventListeners同模块导出的函数,需要正确Spy该模块,而非instance(除非instance是模块的实例化对象)。
修正后的测试代码
// 假设你的模块名为eventHandlers.js,先导入模块 import * as eventHandlers from './eventHandlers'; describe("unit tests", () => { test('setEventListeners: should call createBlob on click', async () => { // 1. Spy on createBlob函数,模拟空实现避免实际执行 const createBlobSpy = jest.spyOn(eventHandlers, 'createBlob').mockImplementation(() => {}); // 2. 模拟按钮元素,实现必要的DOM方法 const mockButton = { getAttribute: jest.fn().mockReturnValue(null), // 初始无listener属性,满足进入分支的条件 setAttribute: jest.fn(), addEventListener: jest.fn((event, handler) => { // 绑定事件时直接触发handler,模拟点击行为 if (event === 'click') { handler(); } }) }; // 3. Mock document.querySelectorAll,返回包含mockButton的NodeList document.querySelectorAll = jest.fn().mockReturnValue([mockButton]); // 4. 调用测试函数 await eventHandlers.setEventListeners({/* 传入你的mock dateBlob对象 */}, "1"); // 5. 断言验证 expect(createBlobSpy).toHaveBeenCalledWith("#weekly", expect.any(Object)); expect(mockButton.setAttribute).toHaveBeenCalledWith("listener", "true"); expect(mockButton.addEventListener).toHaveBeenCalledWith("click", expect.any(Function)); }); // 测试后清理mock,避免影响其他用例 afterEach(() => { jest.restoreAllMocks(); }); });
额外注意事项
- 如果
createBlob是全局函数或其他模块的方法,需要调整jest.spyOn的目标对象。 - 原函数
setEventListeners标记为async但内部无异步操作,测试中可以去掉async/await,保留也不影响结果。 - 若需要测试"已绑定过监听的按钮不再重复绑定"的逻辑,可以添加另一个测试用例,将
mockButton.getAttribute的返回值改为"true",断言addEventListener不会被调用。
内容的提问来源于stack exchange,提问作者Endman888
相关产品推荐
相关产品推荐

