如何测试 React 路由 ?

开发 前端
我们知道 @testing-library/react 是运行在 node 环境中的,但浏览器中并没有 HashRouter 或者 BrowserRouter ,所以我们需要一个用到 MemoryRouter

前言

本文承接上文 如何测试 React 异步组件?[1],这次我将继续使用 @testing-library/react[2] 来测试我们的 React 应用,并简要简要说明如何测试路由系统。

基本示例

以下代码使用 react-router V6版本, V5 使用 Switch 包裹组件

通常我们的程序会写下如下代码:

首先我们有 2 个页面

  • src/routes/home.jsx 主页
export default function Home() {
return (
<main style={{ padding: "1rem 0" }}>
<h2>这是主页</h2>
</main>
);
}
  • src/routes/about.jsx 关于页面
export default function Home() {
return (
<main style={{ padding: "1rem 0" }}>
<h2>这是关于页</h2>
</main>
);
}

然后使用 HashRouter 或者 BrowserRouter 包裹,形成我们的程序的主入口index.jsx

  • src/index.jsx 程序入口
import { HashRouter, Routes, Route, Link } from "react-router-dom";
import Home from "./routes/home";
import About from "./routes/about";

const NoMatch = () => <div>No Found</div>;

function App() {
return (
<HashRouter>
<div>
<Link to="/">主页</Link>
<Link to="/about">关于</Link>
</div>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="*" element={<NoMatch />} />
</Routes>
</HashRouter>
);
}

export default App;

因为我们的页面足够简单,所以页面不会报错,那如果当页面变量的复杂,页面下的其中一个组件报错,就会引起白屏

例如 现在在 about 页面下添加一个错误组件

import React from "react";

function AboutContent() {
throw new Error("抛出一个测试错误");
}

export default function About() {
return (
<main style={{ padding: "1rem 0" }}>
<h2>这是关于页</h2>
<AboutContent />
</main>
);
}

此时页面就会报错,但如果我们没有点击 about 页面,我们的程序仍然正常运行,所以我们需要对路由进行测试。

测试方法

我们知道 @testing-library/react 是运行在 node 环境中的,但浏览器中并没有 HashRouter 或者 BrowserRouter ,所以我们需要一个用到 MemoryRouter

此时我们需要将原先的 index.jsx 拆分到app.jsx

  • src/index.jsx 入口
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import { HashRouter } from "react-router-dom";

ReactDOM.render(
<React.StrictMode>
<HashRouter>
<App />
</HashRouter>
</React.StrictMode>,
document.getElementById("root")
);
  • src/app.jsx
import { HashRouter, Routes, Route, Link } from "react-router-dom";
import Home from "./routes/home";
import About from "./routes/about";

const NoMatch = () => <div>No Found</div>;

function App() {
return (
<HashRouter>
<div>
<Link to="/">主页</Link>
<Link to="/about">关于</Link>
</div>
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="*" element={<NoMatch />} />
</Routes>
</HashRouter>
);
}

export default App;

此时我们可以添加单元测试

import { render, screen } from "@testing-library/react";
import userEvent from "@testing-library/user-event";
import { createMemoryHistory } from "history";
import React from "react";
import { Router } from "react-router-dom";
import App from "./App";

test("测试整个路由系统", () => {
render(
<MemoryRouter>
<App />
</MemoryRouter>
);
expect(screen.getByText(/这是主页/i)).toBeInTheDocument();

userEvent.click(screen.getByText(/关于/i));
expect(screen.getByText(/这是关于页/i)).toBeInTheDocument();
});

MemoryRouter[3] 有2个参数

  • 第一个参数 initialEntries={["/users/mjackson"]} 配置初始化路由
  • 第二个参数 initialIndex 默认是 initialEntries 中的最后一个值

测试 404 页面

test('测试路由未匹配', () => {
render(
<MemoryRouter initialEntries={['/some/bad/route']}>
<App />
</MemoryRouter>,
)

expect(screen.getByText(/Not Found/i)).toBeInTheDocument()
})

通用测试

当页面有多个的时候,我们可以添加一个通用组件来确保每个页面都没有错误

import { useLocation } from "react-router-dom";

export const LocationDisplay = ({ children }) => {
const location = useLocation();

return (
<>
<div data-testid="location-display">{location.pathname}</div>
{children}
</>
);
};

将 url 显示在页面上, 通过遍历确保每个页面可以正确渲染。

let routes = ["/", "/about"];

routes.forEach((route) => {
test(`确保 ${route} 的 url 可以正确显示`, () => {
render(
<MemoryRouter initialEntries={[route]}>
<LocationDisplay>
<App />
</LocationDisplay>
</MemoryRouter>
);

expect(screen.getByText(new RegExp(route))).toBeInTheDocument();
});
});

小结

以下是路由测试的步骤:

  • 将程序和使用什么路由分开;
  • 使用 MemoryRouter 来测试;
  • 通过 userEvent.click[4] 点击确保页面可以正确渲染;
  • 提供一个公共包裹组件,通过遍历来测试每个页面,确保渲染

以上就是本文的全部内容,那么如何测试 react hooks ?请关注我,我会尽快出 React test 系列的下文。

参考资料

[1]如何测试 React 异步组件?: https://juejin.cn/post/7046686808377131039

[2]@testing-library/react: https://testing-library.com/

[3]MemoryRouter: https://reactrouter.com/docs/en/v6/api#memoryrouter

[4]userEvent.click: url

责任编辑:武晓燕 来源: JS酷
相关推荐

2022-04-14 08:00:00

Cypress测试开发

2022-08-22 16:23:11

React特性

2017-03-21 21:37:06

组件UI测试架构

2022-09-14 12:00:51

React路由库前端

2017-12-11 08:56:50

2010-10-11 10:33:51

linksys无线路由

2009-11-20 18:04:01

路由交换测试技术

2021-06-08 09:35:11

Cleaner ReaReact开发React代码

2017-09-13 15:05:10

React前端单元测试

2017-09-10 17:41:39

React全家桶单元测试前端测试

2022-10-26 08:00:49

单元测试React

2009-12-22 09:30:37

2023-11-29 11:31:03

2023-11-06 08:00:00

ReactJavaScript开发

2023-11-27 08:24:57

FormikReact

2023-06-16 09:08:39

ReactContextRFC

2019-07-15 11:00:24

ReactNode前端

2017-08-09 08:52:00

2022-05-15 22:08:58

ReactHookdebounce

2022-08-03 09:11:31

React性能优化
点赞
收藏

51CTO技术栈公众号