Ber*_*eli 5 reactjs react-testing-library react-hooks
我有一个自定义钩子,可以在挂载时进行 API 调用并处理状态(isLoading、isError、数据、重新获取);
钩子非常简单:
const useFetch = (endpoint, options) => {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [trigger, setTrigger] = useState(true);
const triggerSearch = () => {
setTrigger(!trigger);
};
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch(
`${process.env.API_URL}${endpoint}`
);
const json = await response.json();
setData(json);
setIsLoading(false);
} catch (error) {
setError(error);
setIsLoading(false);
}
};
fetchData();
}, [endpoint, trigger]);
return {
data,
isLoading,
error,
triggerSearch,
};
};
Run Code Online (Sandbox Code Playgroud)
当尝试测试钩子时,我使用 jest 和testing-library/react。
在react 18中,不再支持testing-library中的react-hooks,因此我无法使用renderHook中的awaitForNextUpdate,因为它不返回它。
相反,我们应该使用 act 和 waitFor - 我已经这样做并且测试通过了。
问题是我收到以下错误
警告:测试中对 TestComponent 的更新未包含在 act(...) 中。
Run Code Online (Sandbox Code Playgroud)When testing, code that causes React state updates should be wrapped into act(...):
test("should make an API call on mount", async () => {
const hook = renderHook(() => useFetch("/api"));
await act(async () => {
await waitFor(() => expect(fetch).toHaveBeenCalledTimes(1));
});
expect(fetch).toHaveBeenCalledTimes(1);
expect(getAccessTokenSilently).toHaveBeenCalledTimes(1);
expect(hook.result.current.data).toEqual({ message: "Test" });
expect(hook.result.current.isLoading).toEqual(false);
expect(hook.result.current.error).toEqual(null);
});
Run Code Online (Sandbox Code Playgroud)
有人可以指出我正确的方向吗?我尝试删除所有断言并仅调用 renderHook,这也会导致相同的错误。
所以我解决这个问题的方法是在 async act 中包含调用 setState 函数的所有内容(包括 renderhook 的初始化,因为它通过 useEffect 调用 api):
describe("useFetch", () => {
test("should make a call to the API and return the message", async () => {
let hook;
await act(async () => {
hook = renderHook(() => useFetch("/api"));
});
const { result } = hook;
expect(fetch).toHaveBeenCalledTimes(1);
expect(getAccessTokenSilently).toHaveBeenCalledTimes(1);
expect(result.current.data).toEqual({ message: "Test" });
expect(result.current.isLoading).toEqual(false);
expect(result.current.error).toEqual(null);
});
});
Run Code Online (Sandbox Code Playgroud)
哦,并确保你正在导入行为@testing-library/react
| 归档时间: |
|
| 查看次数: |
11817 次 |
| 最近记录: |