Ankit Saxena
Ankit Saxena

Reputation: 1197

How to test catch block in jest and react testing library while mocking API calls?

I have a component in which the state gets updated depending upon the response from the API call. I am able to test if data returned from the API is being rendered on screen or not. But I don't know how to test that a proper message (i.e errorMessage) is being shown when API call is failing.

Component :

import React, { useState } from "react";
import { getTodos } from "./Api";

interface responseType {
    completed: boolean;
    id: number;
    title: string;
    userId: number;
}

const Todo: React.FC = () => {
    const [isSuccess, set_isSuccess] = useState(false);
    const [errorMessage, set_errorMessage] = useState('');
    const [data, set_data] = useState<responseType[]>([]);

    const handleFetchData = () => {
        getTodos()
            .then((response) => {
                if (response) {
                    set_isSuccess(true);
                    set_data(response.slice(0, 4))
                }
            })
            .catch((error) => {
                console.log(error);
                set_errorMessage('Failed to fetch data');
            });

    };
    return (
        <>
            <h2>Demo App</h2>
            <button onClick={handleFetchData}>Click</button>
            <div>
                {isSuccess ?
                    data.map((val) => val.title) : errorMessage}
            </div>

        </>
    )
}

export default Todo;

In the above code getTodos() is the function for making the API call. I can test the scenario when API call is successfull. Below is the test file.

import { render, screen, waitFor } from '@testing-library/react';
import Todo from './Todo';
import userEvent from '@testing-library/user-event';

jest.mock('./Api', () => ({
  getTodos: jest.fn(() =>
    Promise.resolve([
      {
        completed: false,
        id: 1,
        title: "a sample item",
        userId: 1
      }])
  )
})
)

it('data fetched successfully', async () => {
  render(<Todo />)
  const btn = screen.getByRole('button', { name: 'Click' })
  userEvent.click(btn);
  await waitFor(() => screen.getByText(/a sample item/i));
})

I want to write a similar test case in same file to check if the message 'Failed to fetch data' is rendered on the screen when API call is failed (catch block get excecuted).

Upvotes: 0

Views: 4819

Answers (1)

user18430779
user18430779

Reputation:

Try promise.reject() instead of resolve() for testing the catch part.

import Todo from './Todo';
import userEvent from '@testing-library/user-event';

jest.mock('./Api', () => ({
  getTodos: jest.fn(() =>
    Promise.reject(
      {
        message: "fetch failed"
      })
  )
})
)

it('data fetched successfully', async () => {
  render(<Todo />)
  const btn = screen.getByRole('button', { name: 'Click' })
  userEvent.click(btn);
  await waitFor(() => screen.getByText(/a sample item/i));
})```

Upvotes: 2

Related Questions