模仿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> <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
相关产品推荐
相关产品推荐

