简体   繁体   中英

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 (ie 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).

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));
})```

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM