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

模仿React Testing Library文档的React Router测试失败原因排查

React Router路由测试失败问题排查

我在TypeScript版React应用中,参照React Testing Library官方文档的React Router路由与链接测试示例编写测试用例。文档示例未使用TypeScript,但我认为这不会影响测试结果。对比自身的App、App.test文件与文档示例未发现差异,仅注意到package.json中的依赖版本存在区别,但我对依赖版本并不熟悉。为何配置看似一致的情况下,文档中的测试能通过,而我的测试却失败?

更新:错误截图

错误截图

我的代码文件

App.tsx

import './App.css';
import { Route, Routes, Link } from 'react-router-dom';

function App() {
  const Home = () => <div>here is home</div>
  const Images = () => <div>here is Images</div>

  return (
    <div className="App">
      <Link to="/" >home</Link>&nbsp;
      <Link to="/images" >images</Link>
      <Routes>
        <Route path="/" element={ <Home /> } />
        <Route path="images" element={ <Images /> } />
      </Routes>
      <Footer />
    </div>
  );
}

export default App;

App.test.tsx

import { render, screen } from '@testing-library/react'
import { BrowserRouter, MemoryRouter } from "react-router-dom"
import userEvent from "@testing-library/user-event"
import App from "./App"

describe('Render text', () => {

  it.only('images route test', async () => {
    render(<App />, {wrapper: BrowserRouter})
    expect(screen.getByText(/here is home/i)).toBeInTheDocument()
    const user = userEvent.setup()
    user.click(screen.getByText(/images/i))
    screen.debug()    // <-- shows home page
    expect(screen.getByText(/here is images/i)).toBeInTheDocument()
  })
})

依赖版本对比

文档中的package.json

{
  "name": "demo",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^14.4.3",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^6.15.0",
    "react-scripts": "5.0.1",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  }
}

我的应用中的package.json

{
  "name": "myapp",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^14.0.0",
    "@testing-library/user-event": "^14.4.3",
    "@types/jest": "^27.5.2",
    "@types/node": "^16.18.36",
    "@types/react": "^18.2.13",
    "@types/react-dom": "^18.2.6",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^6.13.0",
    "react-scripts": "5.0.1",
    "typescript": "^4.9.5",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": [
      "react-app",
      "react-app/jest"
    ]
  },
  "browserslist": {
    "production": [
      ">0.2%",
      "not dead",
      "not op_mini all"
    ],
    "development": [
      "last 1 chrome version",
      "last 1 firefox version",
      "last 1 safari version"
    ]
  },
  "devDependencies": {
    "@babel/plugin-proposal-private-property-in-object": "^7.21.11"
  }
}

问题原因与解决方案

核心问题:未等待异步操作完成

userEvent@14+版本的click方法是异步函数,你的测试中直接调用user.click()后立刻断言,此时路由跳转还没完成,页面仍停留在Home页,自然找不到Images页面的文本。

修改后的测试代码

import { render, screen } from '@testing-library/react'
import { BrowserRouter } from "react-router-dom"
import userEvent from "@testing-library/user-event"
import App from "./App"

describe('Render text', () => {
  it.only('images route test', async () => {
    render(<App />, {wrapper: BrowserRouter})
    expect(screen.getByText(/here is home/i)).toBeInTheDocument()
    
    const user = userEvent.setup()
    // 必须await等待点击后的路由跳转完成
    await user.click(screen.getByText(/images/i))
    
    expect(screen.getByText(/here is images/i)).toBeInTheDocument()
  })
})

额外优化建议

测试路由时更推荐使用MemoryRouter而非BrowserRouter,它是专为测试设计的内存路由,不会操作浏览器的真实history:

render(<App />, {wrapper: MemoryRouter})

内容的提问来源于stack exchange,提问作者chocalaca

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 04:34:57