javascriptreactjsreact-testing-libraryvitestreact-testing

How do I properly test a custom fetch hook in react?


I have this custom hook that returns an object. It probably needs some improvement but for now it works as required.

const fetchList = () => {
  const [list, setList] = useState(null);
  const [status, setStatus] = useState("idle");
  const [error, setError] = useState(null);

  useEffect(() => {
    const controller = new AbortController();
    setStatus('pending')
    fetchList(controller) // This is just a simple async fetch callback
    .then((data) => {
      setList(data);
      setStatus('success');
    })
    .catch(error => setError(error))
    return () => controller.abort();
  }, []);

  return { list, status, error };
};

I've been trying to make a unit test but can't seem to test the resolved value of the fetch callback.

I wrote this test

import { act, renderHook, waitFor } from "@testing-library/react";
import fetchTypeList from "./fetchList";
it('should return success status', async () => {
  await waitFor(()=>{
    expect(result.current.status).toBe('success')
  })
})

But all the values getting tested are only up until the initial launch of useEffect and not the resolved nor rejected values of the fetch.


Solution

  • After re-arranging the test, I found out that mounting renderHook outside the test block is what is causing the test to fail. The test should look like the following.

    test('test should succeed', async () => {
      const {result} = renderHook(() => useCustomHook());
      await waitFor(() => expect(result.current.someVariableThatResolves).toBe(resolvedValue))
      expect(result.current.value).toBe(expectedValue)
    })