Для работы с @testing-library/react-hooks необходимо
установить пакет через npm или yarn:
npm install @testing-library/react-hooks --save-dev
или
yarn add @testing-library/react-hooks --dev
Библиотека интегрируется с Jest по умолчанию, однако можно
использовать и другие тестовые раннеры. Для корректной работы следует
убедиться, что версия react совместима с версией
@testing-library/react-hooks.
renderHookФункция renderHook используется для запуска и
тестирования кастомных React-хуков. Она принимает колбэк, возвращающий
хук, и опциональный объект с параметрами:
import { renderHook, act } from '@testing-library/react-hooks';
import { useCounter } from './useCounter';
const { result } = renderHook(() => useCounter());
result — объект, содержащий текущее
состояние хука и функции для обновления.rerender — позволяет повторно вызвать
хук с новыми аргументами.unmount — размонтирует хук, полезно
для проверки очистки эффектов.waitFor и
waitForNextUpdate — используются для
асинхронных операций внутри хука.actФункция act гарантирует, что все изменения состояния и
эффекты хука будут завершены до выполнения ассертов. Применяется как
синхронно, так и с асинхронными функциями:
act(() => {
result.current.increment();
});
expect(result.current.count).toBe(1);
Для асинхронных обновлений:
await act(async () => {
await result.current.fetchData();
});
expect(result.current.data).toEqual(expectedData);
Хуки часто управляют состоянием, поэтому проверка правильного обновления состояния является ключевой задачей.
const { result } = renderHook(() => useCounter());
expect(result.current.count).toBe(0);
act(() => {
result.current.increment();
});
expect(result.current.count).toBe(1);
Особенности:
result.current всегда содержит актуальное значение,
даже после нескольких вызовов act.Для хуков с побочными эффектами (useEffect) важно
проверять их поведение при монтировании и размонтировании:
const effectMock = jest.fn();
function useTestEffect() {
useEffect(() => {
effectMock();
return () => effectMock();
}, []);
}
const { unmount } = renderHook(() => useTestEffect());
expect(effectMock).toHaveBeenCalledTimes(1);
unmount();
expect(effectMock).toHaveBeenCalledTimes(2);
Если эффект выполняет асинхронную операцию, используют
waitForNextUpdate:
const { result, waitForNextUpdate } = renderHook(() => useAsyncData());
await waitForNextUpdate();
expect(result.current.loading).toBe(false);
expect(result.current.data).toEqual(expectedData);
waitForNextUpdate ожидает один цикл обновления
состояния. Для множественных обновлений используется цикл или
waitFor.
renderHook позволяет передавать параметры в хук и
изменять их без пересоздания:
const { result, rerender } = renderHook(({ initial }) => useCounter(initial), {
initialProps: { initial: 0 },
});
expect(result.current.count).toBe(0);
rerender({ initial: 5 });
expect(result.current.count).toBe(5);
Такой подход полезен для тестирования реактивного поведения хуков при изменении входных данных.
Если хук использует React.Context, требуется обернуть
его в провайдер через опцию wrapper:
const wrapper = ({ children }) => <MyContext.Provider value={value}>{children}</MyContext.Provider>;
const { result } = renderHook(() => useMyContext(), { wrapper });
expect(result.current).toBe(value);
wrapper может быть любым компонентом, который
обеспечивает нужный контекст или провайдеры.
act при изменении состояния или
вызове функций хука.waitFor или
waitForNextUpdate, чтобы избежать предупреждений
React.unmount.toEqual или
toMatchObject.rerender для проверки реактивного
поведения хуков при изменении входных данных.wrapper для изоляции тестов.@testing-library/react-hooks совместим с Jest, Mocha и
другими тестовыми фреймворками. В случае Jest можно использовать
мок-функции через jest.fn() для проверки вызовов и
состояния побочных эффектов. Для TypeScript важно правильно типизировать
result.current для корректного автодополнения и проверки
типов.
Хорошо структурированное использование
@testing-library/react-hooks позволяет тестировать хуки так
же надежно, как компоненты, обеспечивая контроль состояния, побочных
эффектов и реактивного поведения в изоляции.