React中useMediaQuery的Jest多返回值模拟失效问题排查
正确模拟Material UI useMediaQuery的Jest测试方案
问题根源
你犯了两个关键错误:
useMediaQuery的返回值是单个布尔值,而非包含多个状态的对象,你之前的mock返回了对象,导致两个变量都被赋值为同一个对象。- 两次调用
useMediaQuery的参数不同,但你用mockReturnValue返回固定值,无法区分不同调用的返回结果。
正确模拟方案
方案一:按调用顺序返回值(适合简单场景)
如果代码中useMediaQuery的调用顺序固定(先print后断点查询),可以用mockReturnValueOnce依次指定返回值:
import { useMediaQuery } from '@mui/material'; // 先模拟print查询返回false,再模拟小屏幕查询返回true useMediaQuery.mockReturnValueOnce(false) .mockReturnValueOnce(true);
注意:此方法依赖调用顺序,若代码中调用顺序变更,测试会失效。
方案二:按参数匹配返回值(更健壮)
通过mockImplementation根据传入的查询参数,返回对应的布尔值,适配任意调用顺序:
import { useMediaQuery } from '@mui/material'; jest.mock('@mui/material', () => ({ ...jest.requireActual('@mui/material'), useMediaQuery: jest.fn((query) => { // 匹配print媒体查询 if (query === 'print') { return false; } // 匹配基于theme的断点查询 if (typeof query === 'function') { // 模拟Material UI的theme对象 const mockTheme = { breakpoints: { down: (breakpoint) => breakpoint === 'md', // 匹配md断点以下的情况 values: { md: 900 } // 对应你项目中实际的md断点像素值 } }; // 执行传入的theme函数,返回匹配结果 return query(mockTheme); } // 默认返回false return false; }) }));
验证效果
修改mock后,你的代码中:
const isPrint = useMediaQuery('print') // 会返回false const isSmallScreen = useMediaQuery(theme => theme.breakpoints.down(theme.breakpoints.values.md)) // 会返回true
此时console.log(isSmallScreen, isPrint)会输出true false,符合预期。
内容的提问来源于stack exchange,提问作者keerti
相关产品推荐
相关产品推荐

