A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://stackoverflow.com/questions/74063562/testing-custom-hooks-react-typescript below:

reactjs - Testing custom hooks react typescript

When you try to call setState mutate the state. We need to use act() function to

make sure all updates related to these “units” have been processed and applied to the DOM before you make any assertions.

Since your fetchData returns a promise, we need to use async act(...), you need React version at least v16.9.0-alpha.0. For more info about act() function, see react-act-example.

react-hook-testing-library re-export act() function from chosen renderer.

Besides, I just use jest.spyOn(axios, 'get').mockResolvedValueOnce() to mock axios.get() method without installing any extra package.

Note: I return response.data, not await response.data.data.

Now, the working unit test should be:

useFetch.ts:

import { useState, useCallback } from 'react';
import axios from 'axios';

export const useFetch = () => {
  const [error, setError] = useState(null);
  const [loading, setLoading] = useState(false);

  const fetchData = useCallback(async (url: string) => {
    setLoading(true);
    try {
      const response = await axios.get(url);
      const data = response.data;
      setLoading(false);
      return data;
    } catch (error: any) {
      if (error.name !== 'AbortError') {
        setLoading(false);
        setError(error.message);
      }
    }
  }, []);

  return { error, loading, fetchData };
};

useFetch.test.ts:

import { useFetch } from './useFetch';
import axios from 'axios';
import { renderHook, act } from '@testing-library/react-hooks';

describe('useFetch', () => {
  it('fetches successfully data from an API', async () => {
    const mockData = { data: 'test response' };
    const axiosGetSpy = jest.spyOn(axios, 'get').mockResolvedValueOnce({ data: mockData })
    const { result } = renderHook(() => useFetch());

    expect(result.current.error).toBe(null);

    await act(async () => {
      await expect(result.current.fetchData('react')).resolves.toEqual(mockData);
    })

    axiosGetSpy.mockRestore();
  });
});

Test result:

 PASS  stackoverflow/74063562/useFetch.test.ts (17.219 s)
  useFetch
    ✓ fetches successfully data from an API (16 ms)

-------------|---------|----------|---------|---------|-------------------
File         | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------|---------|----------|---------|---------|-------------------
All files    |   83.33 |        0 |     100 |   81.25 |                   
 useFetch.ts |   83.33 |        0 |     100 |   81.25 | 16-18             
-------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        21.31 s

package versions:

"@testing-library/react-hooks": "^8.0.1",
"jest": "^26.6.3",
"react": "^16.14.0",
"react-dom": "^16.14.0",

RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4