测试
react-router 依赖 React.context 来正常工作。这会影响你测试组件的方法。
Context
如果尝试对渲染或
建议使用 MemoryRouter 或自定义 history,以便能够在两次测试之间重置路由器。
class Sidebar extends Component {
// ...
render() {
return (
<div>
<button onClick={this.toggleExpand}>expand</button>
<ul>
{users.map(user => (
<li>
<Link to={user.path}>{user.name}</Link>
</li>
))}
</ul>
</div>
)
}
}
// 错误 ❌
test('it expands when the button is clicked', () => {
render(<Sidebar />)
click(theButton)
expect(theThingToBeOpen)
})
// 正确 ✅
test('it expands when the button is clicked', () => {
render(
<MemoryRouter>
<Sidebar />
</MemoryRouter>
)
click(theButton)
expect(theThingToBeOpen)
})
从特定的路由路径开始测试
<MemoryRouter>
支持 initialEntries
和 initialIndex
属性,所以你可以从任意路由开始您的测试。
test('current user is active in sidebar', () => {
render(
<MemoryRouter initialEntries={['/users/2']}>
<Sidebar />
</MemoryRouter>
)
expectUserToBeActive(2)
})
导航
我们进行了大量的测试来确保在 location 变化时候路由能够正确的渲染,所以你不必亲自测试它们。但如果你真的需要, 你可以这样测试:
// app.js (a component file)
import React from 'react'
import { Route, Link } from 'react-router-dom'
// our Subject, the App, but you can test any sub
// section of your app too
const App = () => (
<div>
<Route
exact
path="/"
render={() => (
<div>
<h1>Welcome</h1>
</div>
)}
/>
<Route
path="/dashboard"
render={() => (
<div>
<h1>Dashboard</h1>
<Link to="/" id="click-me">
Home
</Link>
</div>
)}
/>
</div>
)
// you can also use a renderer like "@testing-library/react" or "enzyme/mount" here
import { render, unmountComponentAtNode } from 'react-dom'
import { act } from 'react-dom/test-utils'
import { MemoryRouter } from 'react-router-dom'
// app.test.js
it('navigates home when you click the logo', async => {
// 在真正的测试中 "@testing-library/react" 会为你生成真实测试dom
const root = document.createElement('div')
document.body.appendChild(root)
// 渲染
render(
<MemoryRouter initialEntries={['/my/initial/route']}>
<App />
</MemoryRouter>,
root
)
// 交互
act(() => {
// 找到需要点击的路由
const goHomeLink = document.querySelector('#nav-logo-home')
// 点击
goHomeLink.dispatchEvent(new MouseEvent('click', { bubbles: true }))
})
// 验证正确的路由是否被渲染
expect(document.body.textContent).toBe('Home')
})
在测试中验证 location
您不必在测试中经常访问 location 或 history 对象,但是如果这样做(例如,验证是否在 url 栏中设置了新的查询参数),则可以添加一条路由来更新测试中的变量:
// app.test.js
test('clicking filter links updates product query params', () => {
let history, location
render(
<MemoryRouter initialEntries={['/my/initial/route']}>
<App />
<Route
path="*"
render={({ history, location }) => {
history = history
location = location
return null
}}
/>
</MemoryRouter>,
node
)
act(() => {
// example: 点击 <Link> 到 /products?id=1234
})
// 验证url
expect(location.pathname).toBe('/products')
const searchParams = new URLSearchParams(location.search)
expect(searchParams.has('id')).toBe(true)
expect(searchParams.get('id')).toEqual('1234')
})
备择方案
- BrowserRouter 如果您的测试环境具有浏览器全局变量,window.location 并且也可以使用 window.history(这是 Jest 通过 JSDOM 的默认设置,但是您无法重置测试之间的历史记录)。
- 除了将自定义路由传递给 MemoryRouter 之外,您还可以将基数 Router 与包中的 historyprop 一起使用 history:
React 应用测试包
请参阅官方文档中的示例:使用React Testing Library测试 React Router