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

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:全局配置(推荐)

  1. 在项目根目录创建jest.setup.js文件,加入上述模拟代码;
  2. 修改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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 06:15:21