如何测试使用自定义React Hook的组件?

时间:2019-09-13 15:31:50

标签: reactjs typescript jestjs axios react-hooks

我目前正在用Typescript编写一个React组件,该组件利用了一个称为useAxios的axios-hooks钩子。此钩子的使用示例是here

 export const App = () => {
  const [{ data, loading, error }, refetch] = useAxios(
    "https://api.myjson.com/bins/820fc"
  );

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error!</p>;

  return (
    <div>
      <button onClick={e => refetch()}>refetch</button>
      <pre>{JSON.stringify(data, null, 2)}</pre>
    </div>
  );
};

const rootElement = document.getElementById("root");
render(<App />, rootElement);

我试图弄清楚如何编写一个可以模拟useAxios钩子的测试。我尝试创建基础axios组件的模拟,但无法正常工作:

import React from "react"
import { render } from "@testing-library/react"
import { Test } from "../test"
import useAxios from "axios-hooks"

jest.mock("axios-hooks")
const mockedAxios = useAxios as jest.Mocked<typeof useAxios>

it("Displays loading", () => {
  // How to mock the return values in the following line?
  // mockedAxios.

  const { getByText } = render(<Test />)

  expect(getByText("Loading...")).toBeDefined()
})

我知道我不必模拟axios,它是基础的依赖项,我应该能够模拟useAxios,但是我还是会尝试的。

我意识到这个问题已经在SO上被多次提及,但是我可以找到针对此特定用例的解决方案。

任何帮助都将不胜感激!

3 个答案:

答案 0 :(得分:1)

我不得不跳过一些额外的步骤,以使编译器对() => undefined参数感到满意。我不喜欢双重as,但我不确定如何降低它的冗长程度,因为我是TS新手。

import * as useAxios from 'axios-hooks';
import { AxiosPromise } from 'axios';
import React from 'react';
import Test from 'components/Test';
import { render } from '@testing-library/react';

jest.mock('axios-hooks');
const mockedUseAxios = useAxios as jest.Mocked<typeof useAxios>;

it('renders a loading message', async () => {
  mockedUseAxios.default.mockImplementation(() => [
    {
      data: [],
      loading: true,
      error: undefined,
    },
    (): AxiosPromise => (undefined as unknown) as AxiosPromise<unknown>,
  ]);

  const { getByText } = render(<Test />);

  expect(getByText('Loading...')).toBeDefined();
});

答案 1 :(得分:0)

模拟模块并设置每个测试useAxios的预期结果,例如

jest.mock('axios-hooks');

import useAxios from 'axios-hooks';

test('App displays loading when request is fetching', () => {
  useAxios.mockReturnValue(Promise.resolve({ loading: true }));
  // mount component
  // Verify "Loading" message is rendered
});

答案 2 :(得分:0)

我自己想出了怎么做。为了测试自定义钩子,我执行了以下操作:

import * as useAxios from "axios-hooks"
jest.mock("axios-hooks")
const mockedAxios = useAxios as jest.Mocked<typeof useAxios>

it("Displays loading message", async () => {

  // Explicitly define what should be returned
  mockedAxios.default.mockImplementation(() => [
      {
        data: [],
        loading: true,
        error: undefined
      },
      () => undefined
    ])

  const { getByText } = render(<Test />)

  expect(getByText("Loading...")).toBeDefined()
})