为什么 useParams during test return undefined in test env with wrapper?

Why does useParams during test return undefined in test env with wrapper?

我现在已经在 2 个不同的代码库中看到了这个,我很困惑,因为它在实际的浏览器中工作正常,但在测试中却不行:如果一个组件使用 useParams 钩子,钩子会在测试:

Error: Uncaught [TypeError: Cannot destructure property accountId of 'undefined' or 'null'.]

我正在使用 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 docs

中的建议使用包装器测试设置

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 route: /mix/overview/nodata

console.log src/test-utils/index.js:20 params: /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 的 recommended work around 在测试中使用 await 让状态变化正确解决。

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

确保,即使你有一个像建议的 Router/Route 的包装器,你要测试的组件也会被一个带有参数的路由包装:

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

您也可以像这样使用 Jest 模拟查询参数:

import ReactRouter from 'react-router'

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

请参阅 以模拟更多 react-router。