如何使用新的React Router挂钩测试组件?

Rem*_*rez 9 react-router

到目前为止,在单元测试中,反应路由器匹配参数已作为组件的道具被检索。因此,考虑具有特定url参数的特定匹配的组件的测试很容易:在渲染测试组件时,我们只需要精确地选择路由器匹配的道具即可(我为此使用了酶库)。

我真的很喜欢用于检索路由的新钩子,但是我没有找到有关如何使用新的React Router钩子在单元测试中模拟React Router匹配的示例?

小智 66

我查看了react-router repo 中钩子的测试,看起来您必须将组件包装在 a MemoryRouterand 中Route。我最终做了这样的事情来使我的测试工作:

import {Route, MemoryRouter} from 'react-router-dom';

...

const renderWithRouter = ({children}) => (
  render(
    <MemoryRouter initialEntries={['blogs/1']}>
      <Route path='blogs/:blogId'>
        {children}
      </Route>
    </MemoryRouter>
  )
)
Run Code Online (Sandbox Code Playgroud)

希望有帮助!

  • 路由器 V6&lt;MemoryRouter initialEntries={['/blogs/1']}&gt;&lt;Routes&gt;&lt;Route path="/blogs/:blogId" element={&lt;PostScreen /&gt;} /&gt;&lt;/Routes&gt; &lt;/MemoryRouter&gt; (8认同)
  • 问题在于模拟新的“react-router-dom”挂钩。对于路由器内的任何被测组件来说,将组件包装在 MemoryRouter 中绝对是您想要做的事情。有多种模式可用于创建可重用包装器,例如 https://testing-library.com/docs/example-react-router (4认同)
  • 这个答案应该被接受,更少干扰,更正确 (3认同)
  • 给出以下错误:`&lt;Route&gt; 只能用作 &lt;Routes&gt; 元素的子元素,从不直接渲染。请将您的 &lt;Route&gt; 包装在 &lt;Routes&gt; 中` (3认同)

小智 24

在您的组件中使用钩子如下

import {useLocation} from 'react-router';

const location = useLocation()
Run Code Online (Sandbox Code Playgroud)

在您对 reactRouter 对象的测试间谍中,如下所示

import routeData from 'react-router';

const mockLocation = {
  pathname: '/welcome',
  hash: '',
  search: '',
  state: ''
}
beforeEach(() => {
  jest.spyOn(routeData, 'useLocation').mockReturnValue(mockLocation)
});
Run Code Online (Sandbox Code Playgroud)

  • 很好,上面的帮助通过使用spyOn感谢@suchin (2认同)
  • 感谢小语法修正:`beforeEach(() =&gt; { jest.spyOn(routeData, 'useLocation').mockReturnValue(mockLocation) });` (2认同)

Mar*_*pse 6

我最终解决问题的方法是使用jest.mock模拟测试中的钩子:

// TeamPage.test.js
jest.mock('react-router-dom', () => ({
  ...jest.requireActual('react-router-dom'), // use actual for all non-hook parts
  useParams: () => ({
    companyId: 'company-id1',
    teamId: 'team-id1',
  }),
  useRouteMatch: () => ({ url: '/company/company-id1/team/team-id1' }),
}));
Run Code Online (Sandbox Code Playgroud)

我曾经使用jest.requireActualreact-router-dom的实际部分来进行除我感兴趣的钩子之外的所有操作。

  • 如果我必须在同一个测试文件中传递不同的 companyId 怎么办 (9认同)
  • 这个答案让我误入歧途,第二高投票的答案(此处)[/sf/answers/4074428501/] 是让组件进入 URL 包含的状态的“幸运”方式您正在寻找的参数,无需模拟。 (3认同)
  • 我从来不知道“jest.requireActual”,这很有帮助! (2认同)

chi*_*imo 6

如果您用于react-testing-library测试,您可以让这个模拟像这样工作。

jest.mock('react-router-dom', () => ({
    ...jest.requireActual('react-router-dom'),
    useLocation: () => ({ state: { email: 'school@edu.ng' } }),
}));

export const withReduxNRouter = (
    ui,
    { store = createStore(rootReducer, {}) } = {},
    {
    route = '/',
    history = createMemoryHistory({ initialEntries: [ route ] }),
    } = {}
) => {
    return {
    ...render(
        <Provider store={store}>
        <Router history={history}>{ui}</Router>
        </Provider>
    ),
    history,
    store,
    };
};
Run Code Online (Sandbox Code Playgroud)

react-router-dom您应该在使用它来渲染组件之前进行模拟。我正在探索使其可重复使用的方法