为什么在测试期间 useParams 在带有包装器的测试环境中返回未定义?

IT技术 reactjs react-router react-router-dom react-testing-library
2021-05-19 05:56:51

我现在已经在 2 个不同的代码库中看到了这一点,但我很难过,因为它在实际浏览器中运行良好,但在测试中却没有:如果组件使用useParams钩子,则钩子会在测试中引发错误:

错误:未捕获 [类型错误:无法解构accountId“未定义”或“空”的属性。]

我正在使用 React 功能组件、React 测试库和 React-Router:

// 零件:

const Overview: FC = () => {
  const location = useLocation();
  console.log(location) // see below
  const { accountId } = useParams();
  console.log(accountId) // see below

  ... rest
}

控制台日志似乎已正确找到参数:

console.log src/screens/Overview/index.tsx:66 accountId: nodata

console.log src/screens/Overview/index.tsx:64 location: { pathname: '/mix/overview/nodata', search: '', hash: '', state: undefined, key: 'bn6zvv' }

// 使用RTL 文档中推荐的包装器测试设置


function renderWithProviders(
  ui,
  {
    route = '/',
    params = routes.root, 
    history = createMemoryHistory({ initialEntries: [route] }),
  } = {},
  apolloMocks
) {
  console.log("route:", route) // see below
  console.log("params:", params) // see below
  return {
    ...render(
      <Provider store={mockProviderStore}>
        <Router history={history}>
          <MockedProvider mocks={apolloMocks}>
            <Route path={params}> // tried to set path to "params" not "route" so the slug of /url/:accountId is properly set
             {ui}
            </Route>
          </MockedProvider>
        </Router>
      </Provider>
    ),
    history,
  };
}

test-utils 文件中的控制台日志结果看起来是正确的:

console.log src/test-utils/index.js:19 路由:/mix/overview/nodata

console.log src/test-utils/index.js:20 参数:/mix/overview/:accountId

// 测试自己

test('it works', async () => {
    const { findByText } = renderWithProviders(<Overview />, {
      route: routes.overview('1234567890'), // => path/1234567890
      params: routes.overview(), // => path/:accountId
    });

    await findByText('loading configs...');

    await waitForElementToBeRemoved(() => getByText('loading configs...'));

    await findByText('View your stuff now. It works!');
  });

我正在尝试从 #kentdodds推荐的解决方法,以await在测试中使用,让状态更改正确解决。

没有正确获取路由参数的 React-Router 钩子是怎么回事?

2个回答

您还可以使用 Jest 模拟查询参数,如下所示:

import ReactRouter from 'react-router'

describe(() => {
  test('...', () => {
    jest.spyOn(ReactRouter, 'useParams').mockReturnValue({ id: '1234' });
    // id = 1234 in your tested component
  });
});

请参阅https://stackoverflow.com/a/58180976/2295549以模拟更多 react-router。

确保,即使您有一个带有路由器/路由的包装器,如建议的那样,您要测试的组件也用带有参数的 Route 包装:

<Route path="/mix/config/:param1/:param2/:param3" >
        <Config />
      </Route>