使用@testing-library/react测试时无法正确mock useAsync钩子问题求助
问题原因
你的问题核心是两处使用错误共同导致的:
useAsync导入/调用方式不符合你用的react-async-hook库的要求,导致返回的result字段没有正确解析Promise,直接返回了未处理的Promise对象- 组件没有判断异步加载状态,且测试断言顺序不合理,在异步未完成时就触发了渲染逻辑
解决步骤
1. 修正useAsync导入方式
react-async-hook 的默认导出才是正确的钩子函数,不要使用解构导入:
// 错误写法 // import { useAsync } from "react-async-hook"; // 正确写法 import useAsync from "react-async-hook";
2. 调整组件逻辑,增加加载状态判断
异步钩子执行过程中会有pending状态,此时返回的结果是未就绪的,需要先判断加载状态避免操作未初始化的值,同时调用异步函数时用箭头函数包裹,避免参数传递异常:
import React from "react"; import useAsync from "react-async-hook"; import { getTest } from "./TestAPI"; export default function TestPanel() { // 用箭头函数包裹getTest调用,增加loading状态获取 const { result: elems, loading } = useAsync(() => getTest(), []); // 加载中直接返回空,避免渲染未就绪的result if (loading) return null; return ( <div> {elems?.map((elem, index) => { // 记得给map遍历的元素加key属性避免React警告 return <div key={index}>{elem}</div>; })} </div> ); }
3. 调整测试代码的断言顺序
React 18 中useEffect默认延后执行,render之后同步断言接口调用的时机太早,应该把接口调用判断放到waitFor中,等待异步逻辑执行完成后统一断言:
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 />); // 等待异步逻辑执行完成后再统一断言 await waitFor(() => { expect(getTest).toHaveBeenCalledTimes(1); expect(getTest).toHaveBeenCalledWith(); expect(screen.getByText("hi there")).toBeInTheDocument(); }); });
内容的提问来源于stack exchange,提问作者Oliver Watkins
相关产品推荐
相关产品推荐

