无法使用 React 测试库模拟 useAsync
Can't mock useAsync with react test library
我正在尝试使用 @testing-library/react 测试使用 useAsync 挂钩的组件。
如果我在 TestAPI 模块上使用 jest.mock,然后是 getTest.mockResolvedValueOnce(testArray);在 getTest 函数上然后我希望模拟正确 return 测试值。
测试:
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”是未定义的。
仔细观察,元素似乎是一个承诺。
我做错了什么吗?
我认为你应该从 useAsync 挂钩本身模拟你的 return。
jest.mock("path/to/useAsync", () => ({
result: ["test"]
}));`
这些是您的问题:react-async-hook & jest
Here react-async-hook
使用 instanceof Promise
但 Jest.mockResolvedValueOnce
returns 不是真正的 JS Promise
,而是一个类似 promise 的对象。因此 useAsync()
将 mock 视为 sycn 函数。
解决方案是使用mockImplementationOnce
代替mockResolvedValueOnce
getTest.mockImplementation(async () => testArray)
来自docs:
mockFn.mockResolvedValueOnce(value)
Syntactic sugar function for:
jest.fn().mockImplementationOnce(() => Promise.resolve(value));
但是,遗憾的是,它不仅仅是语法糖。
我正在尝试使用 @testing-library/react 测试使用 useAsync 挂钩的组件。
如果我在 TestAPI 模块上使用 jest.mock,然后是 getTest.mockResolvedValueOnce(testArray);在 getTest 函数上然后我希望模拟正确 return 测试值。
测试:
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”是未定义的。
仔细观察,元素似乎是一个承诺。
我做错了什么吗?
我认为你应该从 useAsync 挂钩本身模拟你的 return。
jest.mock("path/to/useAsync", () => ({
result: ["test"]
}));`
这些是您的问题:react-async-hook & jest
Here react-async-hook
使用 instanceof Promise
但 Jest.mockResolvedValueOnce
returns 不是真正的 JS Promise
,而是一个类似 promise 的对象。因此 useAsync()
将 mock 视为 sycn 函数。
解决方案是使用mockImplementationOnce
代替mockResolvedValueOnce
getTest.mockImplementation(async () => testArray)
来自docs:
mockFn.mockResolvedValueOnce(value)
Syntactic sugar function for:
jest.fn().mockImplementationOnce(() => Promise.resolve(value));
但是,遗憾的是,它不仅仅是语法糖。