Как подключить с помощью useEffect/setState
У меня проблемы с выполнением следующего теста:
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 | });
Я создал репро кейс в codeandbox:
1 ответ
renderHook
не ждет твоего setTimeout
стрелять; он не может знать, какие "побочные эффекты" есть у вашего компонента. Итак, когда ваш expect()
работает, текущее значение по-прежнему по умолчанию - null
,
Мы можем заставить тест подождать, пока хук не обновится снова, используя waitForNextUpdate
, который находится на объекте renderHook
возвращается. waitForNextUpdate
это функция, которая возвращает обещание, которое разрешается, когда хук снова обновляется (например, когда срабатывает ваш setTimeout).
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({});
});
});