React(TypeScript)单元测试中如何Mock useMediaQuery?
在Jest + Testing-Library中模拟桌面端视口测试React组件
方案1:精准Mock window.matchMedia 匹配你的媒体查询
你的mock无效大概率是因为查询字符串匹配不一致(比如utils.breakpoints.md的值不等于768),直接针对组件中使用的查询字符串返回true即可:
// 在测试文件的顶部或beforeAll块中 beforeAll(() => { Object.defineProperty(window, 'matchMedia', { writable: true, value: jest.fn().mockImplementation(query => ({ matches: query === '(min-width: 768px)', // 完全匹配组件中的查询 media: query, onchange: null, addListener: jest.fn(), removeListener: jest.fn(), addEventListener: jest.fn(), // 兼容新版API removeEventListener: jest.fn(), dispatchEvent: jest.fn(), })), }); }); test('桌面端显示行选择复选框', () => { render(<YourCustomDataTable />); // 断言复选框存在(根据你的组件实际选择器调整) expect(screen.getByRole('checkbox')).toBeInTheDocument(); });
方案2:直接Mock useMediaQuery 钩子(适用于第三方库如MUI)
如果你的useMediaQuery来自第三方库(比如@mui/material),可以跳过媒体查询的模拟,直接让钩子返回桌面端状态:
// 在测试文件顶部mock钩子 jest.mock('@mui/material/useMediaQuery', () => () => true); test('桌面端渲染复选框', () => { render(<YourCustomDataTable />); expect(screen.getByRole('checkbox')).toBeInTheDocument(); });
方案3:动态模拟视口宽度(支持不同尺寸测试)
如果需要测试多种屏幕尺寸,可让matchMedia根据当前window.innerWidth动态返回结果:
beforeAll(() => { window.matchMedia = jest.fn().mockImplementation(query => { // 解析媒体查询中的最小宽度值 const minWidthMatch = query.match(/min-width:\s*(\d+)px/); if (minWidthMatch) { const requiredWidth = parseInt(minWidthMatch[1], 10); return { matches: window.innerWidth >= requiredWidth, media: query, onchange: null, addListener: jest.fn(), removeListener: jest.fn(), addEventListener: jest.fn(), removeEventListener: jest.fn(), dispatchEvent: jest.fn(), }; } return { matches: false, media: query, /* 其他必要属性 */ }; }); }); test('1500px宽时显示复选框', () => { // 设置视口宽度为1500px window.innerWidth = 1500; // 触发resize事件确保媒体查询更新 window.dispatchEvent(new Event('resize')); render(<YourCustomDataTable />); expect(screen.getByRole('checkbox')).toBeInTheDocument(); }); test('700px宽时隐藏复选框', () => { window.innerWidth = 700; window.dispatchEvent(new Event('resize')); render(<YourCustomDataTable />); expect(screen.queryByRole('checkbox')).not.toBeInTheDocument(); });
内容的提问来源于stack exchange,提问作者Pamwamba
相关产品推荐
相关产品推荐

