异步事件处理程序中未调用模拟的 useHistory

时间:2021-01-23 03:14:34

标签: reactjs jestjs react-testing-library

总结

我正在为我的 React 应用编写测试代码,但不知何故,它总是失败。

我的应用代码非常简单,只有一个按钮,如果点击它,就会触发一个函数 handleSubmit

处理程序的作用是

  • 从后端获取数据(这是异步函数)
  • 移至 /complete 页。

我做了什么

  • 我在测试代码中模拟了从 API 获取数据的函数
  • 我模拟了测试代码中的 useHistory

注意

我意识到如果从 API 获取数据的行被注释掉,测试就会通过。

代码

  • 我的主要应用代码
import { useFetchDataFromAPI } from '@/usecase/useFetchDataFromAPI';

  :

  const { fetchDataFromAPI } = useFetchDataFromAPI();

  :

  const handleSubmit = async () => {
    // If the line below is not commented out, test will fail
    // const { id } = await fetchDataFromAPI();
    history.push(`/complete`);
  };

  return (
    <>
      <button onClick={handleSubmit}>Button</button>
    </>
  • 我的测试代码

:

jest.mock('@/usecase/useFetchDataFromAPI', () => ({
  useFetchDataFromAPI: () => {
    return { fetchDataFromAPI: jest.fn((): number => {
        return 1;
    })}
  }
}));

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

:

const renderApplicationWithRouterHistory = () => {
  const history = createMemoryHistory();
  const wrapper = render(
    <Router history={history}>
      <Application />
    </Router>
  );
  return { ...wrapper, history };
};

:

describe('Test onClick handler', async () => {
  test('Submit', () => {
    const { getByText, getByRole } = renderApplication();

    const elementSubmit = getByText('Button');
    expect(elementSubmit).toBeInTheDocument();
    fireEvent.click(elementSubmit);
    expect(mockHistoryPush).toHaveBeenCalled();
  });
});

1 个答案:

答案 0 :(得分:1)

您的事件处理程序在按钮单击时被调用,但由于它是异步的,因此在您的测试运行之后 之前不会评估其结果。在这种特殊情况下,您不需要异步行为,因此只需使用:

const handleSubmit = () => {
  history.push(`/complete`)
}
如果您的处理程序确实需要testing-library 某些东西,

await 会为此提供一个方法 waitFor

await waitFor(() => expect(mockHistoryPush).toHaveBeenCalled())

虽然另一种简单的方法是在测试中简单地等待一个承诺,以便将期望延迟一个滴答:

fireEvent.click(elementSubmit);
await Promise.resolve();
expect(mockHistoryPush).toHaveBeenCalled();