如何在useEffect中使用axios请求测试react组件?

Сла*_*нов 0 typescript reactjs jestjs axios react-testing-library

我已在 useEffect 中对功能组件做出反应。 https://codesandbox.io/s/nifty-dew-r2p1d?file=/src/App.tsx

const App = () => {
  const [data, setData] = useState<IJoke | undefined>(undefined);
  const [isLoading, setIsLoading] = useState<boolean>(true);

  useEffect(() => {
    axios
      .get("https://v2.jokeapi.dev/joke/Programming?type=single")
      .then((res: AxiosResponse<IJoke>) => {
        setData(res.data);
      })
      .catch((err) => console.log(err))
      .finally(() => setIsLoading(false));
  }, []);

  return (
    <div className="App">
      {isLoading ? (
        <h2>Loading...</h2>
      ) : (
        <div className="info">
          <div className="info__cat">
            {data?.category ? `category: ${data.category}` : "bad category"}
          </div>
          <div className="info__joke">
            {data?.joke ? `joke: ${data?.joke}` : "bad data"}
          </div>
        </div>
      )}
    </div>
  );
};
Run Code Online (Sandbox Code Playgroud)

如何通过测试覆盖组件?我需要在请求之前、及时和之后测试状态。在这种情况下如何模拟请求?

sli*_*wp2 7

选项1.使用msw通过拦截网络级别的请求来进行模拟。

\n

选项 2。如果您不想安装任何包和设置,您可以使用为方法jest.spyOn(object, \'method\').mockResolvedValueOnce()创建模拟已解决/拒绝的值。axios.get()

\n

下面的示例使用选项 2。

\n

App.tsx:

\n
import axios, { AxiosResponse } from \'axios\';\nimport React, { useEffect, useState } from \'react\';\n\ninterface IJoke {\n  category: string;\n  joke: string;\n}\n\nexport const App = () => {\n  const [data, setData] = useState<IJoke | undefined>(undefined);\n  const [isLoading, setIsLoading] = useState<boolean>(true);\n\n  useEffect(() => {\n    axios\n      .get(\'https://v2.jokeapi.dev/joke/Programming?type=single\')\n      .then((res: AxiosResponse<IJoke>) => {\n        setData(res.data);\n      })\n      .catch((err) => console.log(err))\n      .finally(() => setIsLoading(false));\n  }, []);\n\n  return (\n    <div className="App">\n      {isLoading ? (\n        <h2>Loading...</h2>\n      ) : (\n        <div className="info">\n          <div className="info__cat">{data?.category ? `category: ${data.category}` : \'bad category\'}</div>\n          <div className="info__joke">{data?.joke ? `joke: ${data?.joke}` : \'bad data\'}</div>\n        </div>\n      )}\n    </div>\n  );\n};\n
Run Code Online (Sandbox Code Playgroud)\n

App.test.tsx:

\n
import { App } from \'./App\';\nimport axios, { AxiosResponse } from \'axios\';\nimport { act, render, screen } from \'@testing-library/react\';\nimport \'@testing-library/jest-dom/extend-expect\';\nimport React from \'react\';\n\ndescribe(\'70450576\', () => {\n  afterEach(() => {\n    jest.restoreAllMocks();\n  });\n  test(\'should render category and joke\', async () => {\n    const mAxiosResponse = {\n      data: { category: \'smart\', joke: \'sam\' },\n    } as AxiosResponse;\n    jest.spyOn(axios, \'get\').mockResolvedValueOnce(mAxiosResponse);\n    render(<App />);\n    expect(screen.getByText(\'Loading...\')).toBeInTheDocument();\n    expect(await screen.findByText(\'category: smart\')).toBeInTheDocument();\n    expect(await screen.findByText(\'joke: sam\')).toBeInTheDocument();\n  });\n});\n
Run Code Online (Sandbox Code Playgroud)\n

测试结果:

\n
import axios, { AxiosResponse } from \'axios\';\nimport React, { useEffect, useState } from \'react\';\n\ninterface IJoke {\n  category: string;\n  joke: string;\n}\n\nexport const App = () => {\n  const [data, setData] = useState<IJoke | undefined>(undefined);\n  const [isLoading, setIsLoading] = useState<boolean>(true);\n\n  useEffect(() => {\n    axios\n      .get(\'https://v2.jokeapi.dev/joke/Programming?type=single\')\n      .then((res: AxiosResponse<IJoke>) => {\n        setData(res.data);\n      })\n      .catch((err) => console.log(err))\n      .finally(() => setIsLoading(false));\n  }, []);\n\n  return (\n    <div className="App">\n      {isLoading ? (\n        <h2>Loading...</h2>\n      ) : (\n        <div className="info">\n          <div className="info__cat">{data?.category ? `category: ${data.category}` : \'bad category\'}</div>\n          <div className="info__joke">{data?.joke ? `joke: ${data?.joke}` : \'bad data\'}</div>\n        </div>\n      )}\n    </div>\n  );\n};\n
Run Code Online (Sandbox Code Playgroud)\n