How to Test React Server Components

React Server Components (RSCs) introduce a new way to render components on the server, which changes how they must be tested compared to traditional client-side components. This article provides a clear, practical guide on how to test React Server Components using unit testing, integration testing, and end-to-end (E2E) testing strategies to ensure your application remains reliable and performant.

Understanding the Testing Challenge

Because React Server Components run exclusively on the server, they do not have access to browser-specific APIs, state hooks (like useState), or lifecycle effects (like useEffect). Instead, they often perform asynchronous operations, such as direct database queries or secure API requests. This means your testing strategy must account for asynchronous rendering and the mock environments needed for server-side APIs.

Method 1: Unit Testing with React Testing Library

To unit test React Server Components, you can use popular tools like Jest or Vitest alongside React Testing Library. Since server components are often asynchronous functions, you cannot render them directly using standard client-side render methods. Instead, you need to resolve the async component before rendering it.

Here is an example of an asynchronous server component:

// ProductCard.jsx
export default async function ProductCard({ fetchProduct }) {
  const product = await fetchProduct();
  return (
    <div>
      <h2>{product.name}</h2>
      <p>{product.price}</p>
    </div>
  );
}

To test this component, resolve the async component function in your test file before passing it to the render function:

// ProductCard.test.jsx
import { render, screen } from '@testing-library/react';
import ProductCard from './ProductCard';

test('renders product details correctly', async () => {
  const mockFetchProduct = jest.fn().mockResolvedValue({
    name: 'Wireless Mouse',
    price: '$29.99',
  });

  // Resolve the async component
  const ResolvedComponent = await ProductCard({ fetchProduct: mockFetchProduct });
  render(ResolvedComponent);

  expect(screen.getByText('Wireless Mouse')).toBeInTheDocument();
  expect(screen.getByText('$29.99')).toBeInTheDocument();
});

Method 2: Mocking Server-Side Data Fetching

When your server components rely on global fetch calls, database clients (like Prisma), or external SDKs, you must mock these dependencies to isolate your component tests.

If your component imports a server action or an external module directly, you can use Jest or Vitest mocking utilities:

// UserProfile.test.jsx
import { render, screen } from '@testing-library/react';
import UserProfile from './UserProfile';
import { getUser } from './db';

// Mock the database call
jest.mock('./db', () => ({
  getUser: jest.fn(),
}));

test('renders user profile data', async () => {
  getUser.mockResolvedValue({ name: 'Alice' });

  const ResolvedComponent = await UserProfile();
  render(ResolvedComponent);

  expect(screen.getByText('Alice')).toBeInTheDocument();
});

Method 3: End-to-End (E2E) Testing

While unit testing is valuable, end-to-end (E2E) testing is often the most reliable method for testing React Server Components. Because RSCs span the boundary between server-side data fetching and client-side hydration, testing them in a real browser environment ensures that everything works seamlessly together.

Tools like Playwright or Cypress run your entire application (including the server) and assert that the correct HTML is sent from the server and hydrated on the client.

// e2e/product.spec.js (Playwright example)
import { test, expect } from '@playwright/test';

test('should render the product page with server-fetched data', async ({ page }) => {
  await page.goto('/products/1');
  
  // Verify that the server-rendered content is visible in the browser
  const productHeader = page.locator('h2');
  await expect(productHeader).toHaveText('Wireless Mouse');
});

Using E2E tests guarantees that your database connections, server routing, and client interactivity interact correctly without requiring complex mocking of React’s internal server-rendering behavior.