我在通过以下测试时遇到了问题:
import { useEffect, useState } from "react";
export function useComponentResources(required) {
const [componentResources, setComponentResources] = useState(null);
useEffect(() => {
if (required) {
// api call
setTimeout(() => setComponentResources({}), 100);
}
}, [required]);
return componentResources;
}
import { renderHook } from "@testing-library/react-hooks";
import { useComponentResources } from "./component-resources.hook";
describe("component-resources.hook", () => {
it("fetches resources when required", () => {
//act
const { result } = renderHook(() => useComponentResources(true));
//assert
expect(result.current).toEqual({});
});
});
它总是失败:
expect(received).toEqual(expected)
Expected value to equal:
{}
Received:
null
Difference:
Comparing two different types of values. Expected object but received null.
7 | const { result } = renderHook(() => useComponentResources(true));
9 | //assert
> 10 | expect(result.current).toEqual({});
11 | });
12 | });
我已经在codesandbox中创建了一个再现案例:
发布于 2019-07-12 18:00:40
renderHook
不会等待你的setTimeout
触发;它不会知道你的组件有什么“副作用”。因此,当您的expect()
运行时,当前值仍然是它的默认值- null
。
我们可以通过使用renderHook
返回的对象上的waitForNextUpdate
来强制测试等待,直到钩子再次更新。waitForNextUpdate
是一个返回promise的函数,一旦钩子再次更新(例如,当您的setTimeout被触发时),promise就会解析。
import { renderHook } from "@testing-library/react-hooks";
import { useComponentResources } from "./component-resources.hook";
describe("component-resources.hook", () => {
it("fetches resources when required", async () => {
const { result, waitForNextUpdate } = renderHook(() => useComponentResources(true));
await waitForNextUpdate();
expect(result.current).toEqual({});
});
});
https://stackoverflow.com/questions/57010192
复制