乐闻世界logo
搜索文章和话题

Jest 单元测试中如何mock useHistory?

4 个月前提问
2 个月前修改
浏览次数87

2个答案

1
2

在使用 Jest 进行单元测试时,如果要测试的组件中使用了 useHistory 这个 hook 从 react-router-dom,我们通常需要对它进行 mock,以便能够控制和测试与路由相关的逻辑。下面是对 useHistory 进行 mock 的步骤和示例:

步骤 1: 设置 Jest 测试文件

首先,你需要在你的 Jest 测试文件中引入必要的模块,并准备好你的组件。

javascript
import React from 'react'; import { render, fireEvent } from '@testing-library/react'; import { Router } from 'react-router-dom'; import { createMemoryHistory } from 'history'; import MyComponent from './MyComponent'; // 假设这是你需要测试的组件

步骤 2: Mock useHistory

接下来,我们使用 mock 来模拟 useHistory。这里有两种常见的方式来实现:

方式一:直接在测试中改写 useHistory

你可以在你的测试文件中直接覆盖 useHistory

javascript
import { useHistory } from 'react-router-dom'; jest.mock('react-router-dom', () => ({ ...jest.requireActual('react-router-dom'), useHistory: jest.fn(), }));

然后在具体的测试用例中,你可以定义 useHistory 应该如何表现:

javascript
test('should navigate to home page on button click', () => { const historyMock = { push: jest.fn(), location: {}, listen: jest.fn() }; useHistory.mockReturnValue(historyMock); const { getByText } = render(<MyComponent />); fireEvent.click(getByText('Go Home')); expect(historyMock.push).toHaveBeenCalledWith('/home'); });

方式二:使用 Router 和 createMemoryHistory

另一种方式是使用 RoutercreateMemoryHistory 来包裹你的组件,这样可以更灵活地控制路由的状态。

javascript
test('should navigate on button click', () => { const history = createMemoryHistory(); const { getByText } = render( <Router history={history}> <MyComponent /> </Router> ); fireEvent.click(getByText('Go Home')); expect(history.location.pathname).toBe('/home'); });

步骤 3: 执行和验证

无论选择哪种方式,最终你都需要执行你的测试命令来运行测试,并验证它们是否按预期工作。你可以使用 npm test 或你配置的任何特定命令来运行 Jest。

总结

Mocking useHistory 可以通过直接 mock useHistory 或使用 RoutercreateMemoryHistory 这两种方式来实现。选择哪种方式取决于个人或团队对测试策略的偏好。如果你的组件深度依赖于路由行为,使用 RoutercreateMemoryHistory 可能会更合适。

2024年6月29日 12:07 回复

在Jest单元测试中,当你需要模拟 useHistory 这个 React Router 的钩子时,可以使用 jest.mock 来创建一个模拟。由于 useHistory 是一个钩子,我们通常会模拟整个 react-router-dom 模块,并提供一个自定义的 useHistory 实现。以下是如何做到这一点的具体步骤:

  1. 使用 jest.mock
    在你的测试文件的顶部,使用 jest.mock 来模拟 react-router-dom 模块。

  2. 提供 mock 实现
    在模拟中提供一个 useHistory 的替代实现。

  3. 编写测试
    在你的单元测试中使用模拟的 useHistory

下面是一个代码示例:

jsx
// 导入必要的依赖 import { render, screen } from '@testing-library/react'; import React from 'react'; import { Router } from 'react-router-dom'; import { createMemoryHistory } from 'history'; import MyComponent from './MyComponent'; // 假设这是你要测试的组件 // 使用jest.mock来模拟react-router-dom模块 jest.mock('react-router-dom', () => { // 获取原始模块,以便能够使用未被模拟的部分 const originalModule = jest.requireActual('react-router-dom'); // 创建一个模拟的history对象 const history = createMemoryHistory(); // 返回你的模拟 return { ...originalModule, useHistory: () => ({ push: history.push, location: history.location, listen: history.listen }), }; }); test('MyComponent interacts with history correctly', () => { // 使用Router来包裹你的组件 const history = createMemoryHistory(); render( <Router history={history}> <MyComponent /> </Router> ); // 编写你的测试逻辑,检查是否正确地与mock的useHistory进行交互 // 例如,模拟用户点击导致路由改变 screen.getByText('Some button text').click(); expect(history.location.pathname).toBe('/expected-path'); });

在这个例子中,我们使用了 createMemoryHistory 来创建一个内存历史对象,这是一个在测试中常用的技术,因为它允许我们模拟导航操作并检查期望的路径更改是否发生。通过模拟 useHistory,我们能够控制并验证组件是如何与 React Router 的 history 对象交互的。

2024年6月29日 12:07 回复

你的答案