如何在Jest中模拟DOM方法?及指定useEffect代码的模拟方案
在Jest中模拟DOM方法及目标代码测试方案
一、核心模拟思路
Jest内置jsdom环境可模拟浏览器DOM,但针对链式调用的DOM方法,需分层mock每个调用步骤:
- 先mock
document.getElementById,让它返回带有querySelector方法的对象 - 再mock
querySelector,让它返回带有setAttribute方法的对象 - 最后验证
setAttribute是否按预期被调用
二、具体测试代码实现
假设目标逻辑在组件FormComponent.jsx中,对应的测试文件FormComponent.test.jsx代码如下:
import { render } from '@testing-library/react'; import FormComponent from './FormComponent'; describe('FormComponent', () => { it('sets input type to password on component mount', () => { // 1. 跟踪setAttribute的调用 const mockSetAttribute = jest.fn(); // 2. 模拟querySelector返回带setAttribute的元素 const mockQuerySelector = jest.fn(() => ({ setAttribute: mockSetAttribute })); // 3. 模拟getElementById返回带querySelector的元素 const mockGetElementById = jest.fn(() => ({ querySelector: mockQuerySelector })); // 替换原生document.getElementById为mock函数 global.document.getElementById = mockGetElementById; // 渲染组件触发useEffect render(<FormComponent />); // 验证各方法的调用参数是否正确 expect(mockGetElementById).toHaveBeenCalledWith('firstname'); expect(mockQuerySelector).toHaveBeenCalledWith('input-field'); expect(mockSetAttribute).toHaveBeenCalledWith('type', 'password'); }); });
三、边界场景测试
如果DOM元素可能不存在,可调整mock来测试容错逻辑:
it('does nothing when target elements do not exist', () => { const mockSetAttribute = jest.fn(); // 模拟querySelector返回null const mockQuerySelector = jest.fn(() => null); const mockGetElementById = jest.fn(() => ({ querySelector: mockQuerySelector })); global.document.getElementById = mockGetElementById; render(<FormComponent />); // 确认setAttribute未被调用 expect(mockSetAttribute).not.toHaveBeenCalled(); });
四、测试后清理
为避免mock影响其他测试用例,可在每个测试结束后恢复原生方法:
afterEach(() => { jest.restoreAllMocks(); });
内容的提问来源于stack exchange,提问作者Akshay phalphale
相关产品推荐
相关产品推荐

