You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 01:01:18