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

如何在React单元测试中模拟屏幕尺寸测试MUI响应式组件

问题根因

测试运行在JSDOM环境中,该环境默认没有实现window.matchMedia API,Material UI的useMediaQuery钩子无法获取到正确的屏幕匹配结果,默认返回false,因此始终渲染非中等屏幕的按钮,导致找不到mediumScreenButton元素。

解决步骤
  • 实现可自定义宽度的matchMedia mock方法,覆盖MUI依赖的所有API属性
  • 在对应屏幕尺寸的测试用例中,传入对应断点区间的宽度值,挂载mock后再渲染组件
  • 测试结束后重置mock,避免影响其他测试用例

具体实现代码

1. 编写matchMedia mock工具方法

MUI默认主题的md断点对应宽度范围是960px ~ 1279.95px,如果你自定义过主题断点,请替换为自己项目的断点数值:

const createMatchMedia = (screenWidth) => {
  return (query) => ({
    matches: screenWidth >= 960 && screenWidth < 1280, // 匹配md断点区间
    media: query,
    onchange: null,
    addListener: jest.fn(), // 兼容旧版媒体查询API
    removeListener: jest.fn(),
    addEventListener: jest.fn(),
    removeEventListener: jest.fn(),
    dispatchEvent: jest.fn(),
  })
}

2. 修改测试用例

在中等屏幕测试用例渲染组件前,挂载中等宽度(比如1024px,属于md区间)的matchMedia mock:

import React from 'react';
import { render, fireEvent, screen, cleanup } from '@testing-library/react';
import Demo from './Demo'

// 可放到单独的测试工具文件复用
const createMatchMedia = (screenWidth) => {
  return (query) => ({
    matches: screenWidth >= 960 && screenWidth < 1280,
    media: query,
    onchange: null,
    addListener: jest.fn(),
    removeListener: jest.fn(),
    addEventListener: jest.fn(),
    removeEventListener: jest.fn(),
    dispatchEvent: jest.fn(),
  })
}

beforeEach(() => {
  window.scrollTo = jest.fn();
  window.HTMLDivElement.prototype.scrollIntoView = jest.fn();
});

describe('屏幕尺寸按钮渲染测试', () => {
  afterEach(() => {
    cleanup();
    jest.clearAllMocks(); // 重置所有mock避免用例间互相影响
  });

  it('中等屏幕下渲染对应按钮', () => {
    // 模拟中等屏幕宽度1024px
    window.matchMedia = createMatchMedia(1024);
    const { container } = render(<Demo />)

    const mediumScreenButton = screen.getByTestId('mediumScreenButton');
    fireEvent.click(mediumScreenButton);
    expect(container).toMatchSnapshot();
  });

  // 可补充其他屏幕的测试用例
  it('非中等屏幕下渲染对应按钮', () => {
    // 模拟小屏幕宽度375px
    window.matchMedia = createMatchMedia(375);
    render(<Demo />)
    const otherScreenButton = screen.getByTestId('otherScreenButton');
    expect(otherScreenButton).toBeInTheDocument();
  })
});
注意事项
  • 如果项目自定义了MUI主题的breakpoints配置,必须修改createMatchMedia中的宽度判断逻辑,和项目断点保持一致,否则匹配结果会出错
  • 如果多个测试文件都需要测试响应式逻辑,可以把createMatchMedia方法抽到全局测试配置文件(比如src/setupTests.ts)中,避免重复编写
  • 测试用例中不需要真的修改window.innerWidth,只要mock matchMedia的返回值即可,MUI的useMediaQuery只依赖matchMedia的匹配结果,不直接读取窗口宽度

内容的提问来源于stack exchange,提问作者Gowtham Manthena

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 04:48:18