如何在Enzyme中模拟触发readystatechange事件测试React组件?
模拟document.readystatechange事件测试React组件逻辑
这问题我之前在测试React类组件时也碰到过,确实因为document.readyState是只读属性,直接改它行不通,但有几种实用的方法可以模拟触发事件并验证你的API请求逻辑:
方法1:重写readyState并手动派发事件
我们可以通过Object.defineProperty重写document.readyState的getter,让它返回我们需要的complete状态,然后手动创建并派发readystatechange事件,这样组件里的监听逻辑就会被触发。
举个Jest测试的例子:
import { render } from '@testing-library/react'; import YourComponent from './YourComponent'; import axios from 'axios'; // Mock API请求 jest.mock('axios'); test('发起API请求当document readyState变为complete', () => { // 重写document.readyState的getter,返回'complete' Object.defineProperty(document, 'readyState', { get: () => 'complete', configurable: true, // 允许后续重置 }); // 挂载组件 render(<YourComponent />); // 手动触发readystatechange事件 const event = new Event('readystatechange'); document.dispatchEvent(event); // 断言API请求已被调用 expect(axios.get).toHaveBeenCalled(); // 重置document.readyState,避免影响其他测试 Object.defineProperty(document, 'readyState', { get: () => 'interactive', // 恢复默认值,根据你的测试环境调整 configurable: true, }); });
方法2:直接获取并执行事件回调
如果你不想手动派发事件,也可以通过监听document.addEventListener来拿到组件绑定的回调函数,然后直接调用它,同时确保回调里的readyState是complete。
示例代码:
import { render } from '@testing-library/react'; import YourComponent from './YourComponent'; import axios from 'axios'; jest.mock('axios'); test('验证readystatechange到complete时的逻辑', () => { // 监听document.addEventListener方法 const addEventListenerSpy = jest.spyOn(document, 'addEventListener'); // 挂载组件,触发componentDidMount绑定事件 render(<YourComponent />); // 从spy的调用记录中找到readystatechange的回调函数 const [, callback] = addEventListenerSpy.mock.calls.find( ([eventName]) => eventName === 'readystatechange' ); // 临时修改readyState为complete Object.defineProperty(document, 'readyState', { get: () => 'complete', configurable: true, }); // 直接执行回调 callback(); // 断言API请求已触发 expect(axios.get).toHaveBeenCalled(); // 清理spy和重置readyState addEventListenerSpy.mockRestore(); Object.defineProperty(document, 'readyState', { get: () => 'interactive', configurable: true, }); });
注意事项
- 记得在测试完成后重置
document.readyState和所有mock,避免污染其他测试用例; - 如果你的API请求是异步的,需要用
async/await配合waitFor(React Testing Library)或者setTimeout来等待断言完成; - 不同的测试框架(比如Jest、Mocha)语法略有差异,但核心思路一致:要么模拟状态+派发事件,要么直接调用回调。
内容的提问来源于stack exchange,提问作者Shireesha
相关产品推荐
相关产品推荐

