React-Bootstrap Navbar.Offcanvas导致Jest/Testing-Library测试报错
解决Jest测试中
targetWindow.matchMedia is not a function报错问题 问题场景
使用Bootstrap的Navbar.Offcanvas组件实现响应式导航菜单时,保留该组件运行Jest+Testing Library测试会抛出错误:TypeError: targetWindow.matchMedia is not a function,报错位置在渲染<TodoList />的代码行;注释掉该组件后测试可正常通过。
相关代码
Navbar.Offcanvas组件代码:
<Navbar.Offcanvas id={`offcanvasNavbar-expand-md`} aria-labelledby={`offcanvasNavbarLabel-expand-md`} placement="start" > <Offcanvas.Header closeButton> <Offcanvas.Title id={`offcanvasNavbarLabel-expand-md`}> Navigation </Offcanvas.Title> </Offcanvas.Header> <Offcanvas.Body> <Nav> {pages.map((page) => { return ( <Nav.Item key={page.path}> <Nav.Link href={page.path} eventKey={page.path} onSelect={(k) => setKey(k)} className="layout-nav-link" > {page.name} </Nav.Link> </Nav.Item> ); })} </Nav> </Offcanvas.Body> </Navbar.Offcanvas>
测试代码:
test("Renders TodoList", () => { render(<TodoList />); const todoList = screen.getByText("Todo List"); expect(todoList).toHaveTextContent("Todo List"); }); test("Type into TodoList input box", () => { // Arrange render(<TodoList />); const todoListInput = screen.getByLabelText("TodoId"); // Act fireEvent.change(todoListInput, { target: { value: "Run" }, }); // Assert expect(todoListInput.value).toBe("Run"); // Act fireEvent.change(todoListInput, { target: { value: "" }, }); // Assert expect(todoListInput.value).toBe(""); });
解决方案
报错核心原因是Jest默认使用的jsdom环境未实现window.matchMediaAPI,而Navbar.Offcanvas组件渲染时会调用该API检测屏幕尺寸、触发响应式逻辑,因此导致报错。需要手动模拟这个API:
方法1:单个测试文件中添加模拟
在目标测试文件的最顶部加入以下代码:
// 模拟window.matchMedia API window.matchMedia = jest.fn(() => ({ matches: false, addEventListener: jest.fn(), removeEventListener: jest.fn(), }));
方法2:全局配置(推荐)
- 在项目根目录创建
jest.setup.js文件,加入上述模拟代码; - 修改
jest.config.js(或package.json中的jest配置项),指定全局setup文件:
module.exports = { // 其他配置... setupFilesAfterEnv: ['<rootDir>/jest.setup.js'], };
配置完成后,所有测试文件都会自动加载这个模拟,无需在每个文件中重复添加。
如果需要针对特定测试模拟不同的媒体查询结果,可以动态覆盖返回值:
test("测试移动端导航逻辑", () => { window.matchMedia.mockReturnValue({ matches: true, // 模拟移动端屏幕尺寸 addEventListener: jest.fn(), removeEventListener: jest.fn(), }); // 后续测试逻辑... });
内容的提问来源于stack exchange,提问作者usagibear
相关产品推荐
相关产品推荐

