【问题标题】:Can't mock useAsync with react test library无法使用反应测试库模拟 useAsync
【发布时间】:2021-11-03 12:53:36
【问题描述】:

我正在尝试使用 @testing-library/react 测试使用 useAsync 挂钩的组件。

如果我在 TestAPI 模块上使用 jest.mock,然后是 getTest.mockResolvedValueOnce(testArray);在 getTest 函数上,我希望模拟能够正确返回测试值。

测试:

import React from "react";
import { render, screen, waitFor } from "@testing-library/react";
import TestPanel from "./TestPanel";
import { getTest } from "./TestAPI";

jest.mock("./TestAPI");

it("renders cards correctly", async () => {
  const testArray = ["hi there"];
  getTest.mockResolvedValueOnce(testArray);

  render(<TestPanel />);

  expect(getTest).toHaveBeenCalledTimes(1);
  expect(getTest).toHaveBeenCalledWith();

  await waitFor(() => expect(screen.getByText("hi there")).toBeInTheDocument());
});

要测试的组件:

import React from "react";
import { useAsync } from "react-async-hook";
import { getTest } from "./TestAPI";

export default function TestPanel() {
  const { result: elems } = useAsync(getTest, []);

  return (
    <div>
      {elems &&
        elems.map((elem) => {
          return <div>{elem}</div>;
        })}
    </div>
  );
}

API 调用:

import React from "react";
import axios from "axios";

export async function getTest(): Promise {
  const response = await axios.get("/someservice");

  return response.data || [];
}

但是,如果我运行测试,则会引发异常,指出“elems.map”未定义。

仔细观察,elems 似乎是一个承诺。

是不是我做错了什么?

【问题讨论】:

  • 与其模拟钩子,不如直接使用react-hooks-testing-library 测试它?您可以渲染钩子const {result: hookResult, waitFor} = renderHook(() =&gt; useAsync(getTest, []));,然后等待结果为非空:await waitFor(() =&gt; hookResult.result);,然后编写期望案例:expect(getTest).toHaveBeenCalledTimes(1);

标签: reactjs axios react-hooks react-testing-library react-hooks-testing-library


【解决方案1】:

这些是你的问题:react-async-hook & jest

Here react-async-hook 使用 instanceof PromiseJest.mockResolvedValueOnce 返回的不是真正的 JS Promise,而是类似 promise 的对象。所以useAsync() 将mock 视为一个sycn 函数。

解决办法是用mockImplementationOnce代替mockResolvedValueOnce

getTest.mockImplementation(async () => testArray)

来自docs

mockFn.mockResolvedValueOnce(value)

语法糖函数:

jest.fn().mockImplementationOnce(() => Promise.resolve(value));

但是,遗憾的是,它不仅仅是语法糖。

【讨论】:

  • 好的,谢谢。用你的线替换那条线似乎使它现在对我有用。仍然不完全确定为什么,它仍然有点伤害我的大脑。将阅读您发布的链接。谢谢:)
【解决方案2】:

我认为你应该从 useAsync 钩子本身模拟你的返回。

jest.mock("path/to/useAsync", () => ({
  result: ["test"]
}));`

【讨论】:

  • 我试过这个:jest.mock("react-async-hook/useAsync", () => ({result: ["test"],})); .这是你的意思吗?它似乎不起作用
  • 是的,这是个好主意,但请尝试 this 并确保在顶部进行模拟
猜你喜欢
  • 2021-08-26
  • 2022-07-13
  • 1970-01-01
  • 1970-01-01
  • 2021-08-22
  • 1970-01-01
  • 2021-05-25
  • 2021-02-09
  • 2021-09-04
相关资源
最近更新 更多