Jest中模拟window的DOMContentLoaded事件监听器时mockImplementation用法问题排查
解决DOMContentLoaded事件回调的Jest模拟问题
你这里的mockImplementation写法确实踩了个小坑——它的参数应该是一个函数,而不是直接传入事件名和回调逻辑。你当前的写法会导致addEventListener完全没有按照预期模拟事件监听的行为,自然没法触发回调里的业务逻辑。
正确的模拟方式有两种,根据你的测试需求选择:
方式1:自动触发DOMContentLoaded回调
如果希望组件加载后自动执行DOMContentLoaded的回调逻辑,直接在mock的addEventListener里判断事件名并执行回调:
jest.mock("./utils/window"); let mockWindow; // 修正addEventListener的mock实现 const mockWindowObject = { addEventListener: jest.fn((eventName, callback) => { // 监听到DOMContentLoaded时直接执行回调 if (eventName === 'DOMContentLoaded') { callback(); } }) }; beforeEach(() => { jest.resetModules(); mockWindow = require("./utils/window").default; mockWindow.mockReturnValue(mockWindowObject); // 导入组件时,addEventListener会被调用,自动触发回调 require("./myComponent"); });
方式2:手动控制回调触发时机
如果需要在测试用例的特定阶段手动触发回调(比如先做一些前置断言,再执行回调),可以先把回调函数存起来,之后在测试里调用:
jest.mock("./utils/window"); let mockWindow; let domContentLoadedCallback; // 存储回调函数 const mockWindowObject = { addEventListener: jest.fn((eventName, callback) => { if (eventName === 'DOMContentLoaded') { domContentLoadedCallback = callback; } }) }; beforeEach(() => { jest.resetModules(); domContentLoadedCallback = null; // 重置回调,避免用例污染 mockWindow = require("./utils/window").default; mockWindow.mockReturnValue(mockWindowObject); require("./myComponent"); }); // 测试用例示例 test('DOMContentLoaded回调执行后更新了页面状态', () => { // 先断言初始状态 expect(/* 初始状态的断言 */).toBe(...); // 手动触发回调 domContentLoadedCallback(); // 断言回调执行后的状态 expect(/* 回调执行后的断言 */).toBe(...); });
为什么原来的写法不对?
jest.fn().mockImplementation()只接受一个函数参数,你之前写的mockImplementation("DOMContentLoaded", () => true)会把第一个字符串参数当作函数来处理(显然不符合预期),第二个回调参数会被直接忽略,导致你的addEventListener根本没有处理事件监听的核心逻辑——存储或执行回调函数。
内容的提问来源于stack exchange,提问作者user1486133
相关产品推荐
相关产品推荐

