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

时间:2019-09-26 13:26:42

标签: react-router

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

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

6 个答案:

答案 0 :(得分:21)

在组件中,使用如下所示的钩子

import {useLocation} from 'react-router';

const location = useLocation()

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

import routeData from 'react-router';

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

答案 1 :(得分:10)

我最终解决它的方法是使用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' }),
}));

我使用jest.requireActual来将react-router-dom的实际部分用于我对模拟感兴趣的钩子之外的所有内容。

答案 2 :(得分:4)

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

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

希望有帮助!

答案 3 :(得分:3)

如果您使用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,
    };
};

在将react-router-dom用于呈现组件之前,您应该已经对其进行了模拟。 我正在探索使此方法可重用的方法

答案 4 :(得分:1)

我正在尝试获取是否push中的useHistory函数被调用,但是我无法获得模拟的函数调用...

const mockHistoryPush = jest.fn();

jest.mock('react-router-dom', () => ({
    ...jest.requireActual('react-router-dom'),
    useHistory: () => ({
      push: mockHistoryPush,
    }),
  }));

fireEvent.click(getByRole('button'));
expect(mockHistoryPush).toHaveBeenCalledWith('/help');

它表示当按钮具有mockHistoryPush时未调用onClick={() => history.push('/help')}

答案 5 :(得分:-2)

如果使用enzyme库,我发现了一种不太复杂的方法来解决该问题(使用react-router-dom docs中的本节):

import React from 'react'
import { shallow } from 'enzyme'
import { MemoryRouter } from 'react-router-dom'
import Navbar from './Navbar'

it('renders Navbar component', () => {
  expect(
    shallow(
      <MemoryRouter>
        <Navbar />
      </MemoryRouter>
    )
  ).toMatchSnapshot()
})