如何Mock window.matchMedia设置react-responsive的useMediaQuery断点状态?
如何正确Mock window.matchMedia测试react-responsive的useMediaQuery组件?
问题原因分析
- 自定义Mock失效原因:react-responsive会将你传入的配置对象(如
{ minWidth: 1024 })转换为带括号的标准媒体查询字符串(比如(min-width: 1024px)),但你之前传入Mock的参数是min-width: 1024px(缺少括号),导致mediaQuery.includes(query)无法匹配,最终matches始终返回false。 - match-media-mock失效原因:之前的代码未确保Mock在组件渲染前完全生效,且使用react-test-renderer时缺少状态更新的断言时机,改用react-testing-library更适配这类DOM断言场景。
解决方案一:自定义Jest Mock
修正匹配逻辑,传入完整的媒体查询字符串进行精确匹配:
import { mount } from 'enzyme'; import MyComponent from './MyComponent'; function mockMatchMedia(expectedQuery) { Object.defineProperty(window, 'matchMedia', { writable: true, value: jest.fn().mockImplementation((mediaQuery) => ({ matches: mediaQuery === expectedQuery, media: mediaQuery, onchange: null, addListener: jest.fn(), removeListener: jest.fn(), addEventListener: jest.fn(), removeEventListener: jest.fn(), dispatchEvent: jest.fn(), })), }); } // 测试isLG为true的场景 test("renders with isLG true", () => { mockMatchMedia('(min-width: 1024px)'); const wrapper = mount(<MyComponent />); expect(wrapper.text()).toContain('isLG:true'); }); // 测试isSM为true的场景 test("renders with isSM true", () => { mockMatchMedia('(max-width: 767px)'); const wrapper = mount(<MyComponent />); expect(wrapper.text()).toContain('isSM:true'); }); // 测试isMD为true的场景 test("renders with isMD true", () => { mockMatchMedia('(min-width: 768px) and (max-width: 1023px)'); const wrapper = mount(<MyComponent />); expect(wrapper.text()).toContain('isMD:true'); });
解决方案二:使用match-media-mock库
确保Mock在组件渲染前初始化,结合react-testing-library进行断言:
import { render, screen } from '@testing-library/react'; import { create } from 'match-media-mock'; import MyComponent from './MyComponent'; // 测试isSM(宽度700px) test("shows isSM true when width is 700px", () => { const matchMedia = create(); global.window.matchMedia = matchMedia; matchMedia.setConfig({ type: 'screen', width: 700 }); render(<MyComponent />); expect(screen.getByText(/isSM:true/)).toBeInTheDocument(); }); // 测试isMD(宽度800px) test("shows isMD true when width is 800px", () => { const matchMedia = create(); global.window.matchMedia = matchMedia; matchMedia.setConfig({ type: 'screen', width: 800 }); render(<MyComponent />); expect(screen.getByText(/isMD:true/)).toBeInTheDocument(); }); // 测试isLG(宽度1200px) test("shows isLG true when width is 1200px", () => { const matchMedia = create(); global.window.matchMedia = matchMedia; matchMedia.setConfig({ type: 'screen', width: 1200 }); render(<MyComponent />); expect(screen.getByText(/isLG:true/)).toBeInTheDocument(); });
内容的提问来源于stack exchange,提问作者kar
相关产品推荐
相关产品推荐

