Unit Testing React Components with API Calls Using Jest

Unit Testing React Components with API Calls Using Jest

When building React components that involve fetching data from external APIs, it’s crucial to ensure that the components behave as expected under various conditions. This involves testing not only the component’s rendering logic but also its ability to handle data fetching, loading states, and error handling. In this blog post, we’ll explore how to unit test a React component named Posts, which fetches and displays posts from an external API. We will also discuss how to use Jest’s mocking features to simulate API calls for a robust testing environment.

The Posts Component

The Posts component fetches a list of posts from the JSONPlaceholder API and displays them. Here’s a quick rundown of its functionality:

  • It initializes with an empty list of posts.
  • It fetches the posts from the API on component mount.
  • While the data is loading, it displays a “Loading…” message.
  • Once data is fetched, it renders the posts.

Here’s the component code:

.

				
					import React, { useState, useEffect } from 'react';

function Posts() {
    const [posts, setPosts] = useState([]);

    useEffect(() => {
        fetch('https://jsonplaceholder.typicode.com/posts')
            .then(response => response.json())
            .then(data => setPosts(data))
            .catch(error => console.error('Error fetching data: ', error));
    }, []);

    if (posts.length === 0) {
        return <div>Loading...</div>;
    }

    return (
        <div>
            {posts.map(post => (
                <div key={post.id}>
                    <h3>{post.title}</h3>
                    <p>{post.body}</p>
                </div>
            ))}
        </div>
    );
}

export default Posts;

				
			

Testing Strategy

The testing strategy for the Posts component includes:

  1. Mocking Fetch API: Since the component relies on external API calls, we will mock these calls to control the test environment and avoid making actual HTTP requests.
  2. Testing Loading State: Verify that the component correctly displays the loading state.
  3. Testing Successful Data Fetch: Ensure that the component correctly renders the fetched data.
  4. Error Handling: Optionally, you could also test how the component handles a failed API call (not covered here, but recommended).

Using Jest to Mock Fetch API

Jest.fn() and Mocking Modules

jest.fn() is a function that returns a new, unused mock function. Alternatively, you can use jest.spyOn() to spy or mock functions or methods.

Mocking Fetch

Here is how you can mock the fetch function globally using Jest:

				
					global.fetch = jest.fn(() =>
  Promise.resolve({
    json: () => Promise.resolve(fakePosts)
  })
);

				
			

Writing Tests

Now, let’s write some tests using React Testing Library alongside our Jest mocks:

				
					import React from 'react';
import { render, screen, waitFor } from '@testing-library/react';
import Posts from './Posts';

const fakePosts = [
  { id: 1, title: 'Post 1', body: 'This is post 1' },
  { id: 2, title: 'Post 2', body: 'This is post 2' }
];

beforeEach(() => {
  fetch.mockClear();
  fetch.mockImplementation(() =>
    Promise.resolve({
      json: () => Promise.resolve(fakePosts)
    })
  );
});

test('displays loading message initially', () => {
  render(<Posts />);
  expect(screen.getByText('Loading...')).toBeInTheDocument();
});

test('displays posts after fetch', async () => {
  render(<Posts />);
  await waitFor(() => {
    expect(screen.getByText('Post 1')).toBeInTheDocument();
    expect(screen.getByText('This is post 1')).toBeInTheDocument();
    expect(screen.getByText('Post 2')).toBeInTheDocument();
    expect(screen.getByText('This is post 2')).toBeInTheDocument();
  });
});

				
			

      Mocking API calls using Jest and testing asynchronous behavior are critical parts of ensuring that React components with external dependencies behave correctly. By using `jest.fn()` to mock functions and controlling the fetch API responses, you can simulate various scenarios and effectively test your React components.

Overview

Leave a Reply

Your email address will not be published. Required fields are marked *

Enquire Now