React 18+Vite测试时window.matchMedia报matches未定义错误求助
解决window.matchMedia测试时的TypeError问题
问题说明
React 18 + Vite项目中,window.matchMedia在生产环境和本地运行完全正常,但测试阶段抛出错误:
TypeError: Cannot read properties of undefined (reading 'matches')
按照Jest手动Mock的文档方案,在setupTests.js中添加了Mock代码,但并未生效:
Object.defineProperty(window, 'matchMedia', { writable: true, value: vi.fn().mockImplementation(query => ({ matches: false, media: query, onchange: null, addListener: vi.fn(), // deprecated removeListener: vi.fn(), // deprecated addEventListener: vi.fn(), removeEventListener: vi.fn(), dispatchEvent: vi.fn(), })), })
解决方案
1. 匹配测试框架的Mock函数
如果项目用的是Jest,需把代码中的vi.fn()替换为jest.fn()——两者属于不同测试框架的Mock工具,不能混用:
Object.defineProperty(window, 'matchMedia', { writable: true, value: jest.fn().mockImplementation(query => ({ matches: false, media: query, onchange: null, addListener: jest.fn(), removeListener: jest.fn(), addEventListener: jest.fn(), removeEventListener: jest.fn(), dispatchEvent: jest.fn(), })), })
如果用的是Vite默认的Vitest,则保留vi.fn()即可。
2. 确保setup文件被正确加载
- Vitest环境:在
vite.config.js的test配置中指定setup文件路径:
export default defineConfig({ test: { setupFiles: ['./src/setupTests.js'], // 其他测试配置项 }, })
- Jest环境:在
jest.config.js中配置setupFilesAfterEnv:
module.exports = { setupFilesAfterEnv: ['./src/setupTests.js'], // 其他Jest配置项 }
注意路径要和你的实际文件位置一致。
3. 提前Mock避免调用时机问题
如果组件在挂载时就调用了matchMedia,可能全局setup的Mock还未生效。可以在单个测试文件中提前Mock:
beforeAll(() => { window.matchMedia = jest.fn().mockImplementation(query => ({ matches: false, media: query, onchange: null, addListener: jest.fn(), removeListener: jest.fn(), addEventListener: jest.fn(), removeEventListener: jest.fn(), dispatchEvent: jest.fn(), })) })
4. 排查Mock是否被覆盖
有些第三方库或测试工具可能会修改window.matchMedia,可以在测试代码中打印验证:
console.log(window.matchMedia)
输出应为你定义的Mock函数,而非undefined或原生函数。
内容的提问来源于stack exchange,提问作者Shane
相关产品推荐
相关产品推荐

