Home » How to Mock LLM APIs When Testing React Components
React • Technology

How to Mock LLM APIs When Testing React Components

AI-powered React applications are becoming increasingly common, from chatbots and intelligent search to automated content generation. However, testing these applications introduces challenges such as unpredictable model responses, API costs, network failures, and latency.

Mocking LLM APIs allows developers to test React components using controlled responses without repeatedly calling real AI services.

In this guide, we’ll explore how to mock LLM APIs using Vitest, React Testing Library, and Mock Service Worker (MSW), along with practical insights from GeekyAnts, Microsoft, Vercel, OpenAI, and Thoughtworks.

Why Mock LLM APIs in React?

Calling a real LLM API during every component test can make your test suite expensive and unreliable.

Common challenges include:

  • Unpredictable responses: Model outputs can vary between requests.
  • API costs: Repeated calls consume provider credits.
  • Network latency: Tests become slower and less consistent.
  • Rate limits: Automated test suites may exceed provider limits.
  • Error handling: Real API failures are difficult to reproduce consistently.
  • Streaming responses: Interfaces must handle partially generated content.

Mocking solves these problems by replacing live API responses with predictable test data.

However, mocks only verify how your application handles predefined scenarios. They do not establish whether an actual LLM produces accurate or useful answers.

Tools for Mocking LLM APIs

ToolPurpose
VitestRuns tests and provides mocking utilities.
React Testing LibraryTests React components through user interactions.
MSWIntercepts HTTP requests and returns simulated responses.
PlaywrightTests complete browser interactions with mocked network requests.
Vercel AI SDK testing utilitiesSimulates language-model responses for applications using the SDK.

For most React applications, Vitest + React Testing Library + MSW provides a practical starting point. Refer to the

How to Mock an LLM API in React: Step-by-Step

1. Install dependencies

npm install -D vitest jsdom \
  @testing-library/react \
  @testing-library/jest-dom \
  @testing-library/user-event \
  msw

2. Create an MSW handler

Create src/test/handlers.ts:

import { http, HttpResponse } from 'msw';

export const handlers = [
  http.post('/api/ai/chat', async ({ request }) => {
    const body = await request.json() as {
      message: string;
    };

    return HttpResponse.json({
      message: `Mock response to: ${body.message}`,
    });
  }),
];

This intercepts requests to /api/ai/chat and returns a predictable response without contacting a real LLM.

3. Configure the mock server

Create src/test/server.ts:

import { setupServer } from 'msw/node';
import { handlers } from './handlers';

export const server = setupServer(...handlers);

Create src/test/setup.ts:

import '@testing-library/jest-dom/vitest';
import { beforeAll, afterAll, afterEach } from 'vitest';
import { cleanup } from '@testing-library/react';
import { server } from './server';

beforeAll(() => {
  server.listen({ onUnhandledRequest: 'error' });
});

afterEach(() => {
  cleanup();
  server.resetHandlers();
});

afterAll(() => {
  server.close();
});

Configure Vitest to use this setup file and the jsdom environment.

4. Test the React component

Suppose your AIChat component submits a prompt to /api/ai/chat and displays the returned message.

Create AIChat.test.tsx:

import { it, expect } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { AIChat } from './AIChat';

it('displays the mocked AI response', async () => {
  const user = userEvent.setup();

  render(<AIChat />);

  await user.type(
    screen.getByLabelText('Enter your question'),
    'What is React?'
  );

  await user.click(
    screen.getByRole('button', { name: 'Ask AI' })
  );

  expect(
    await screen.findByText(
      'Mock response to: What is React?'
    )
  ).toBeInTheDocument();
});

This test simulates a real user interaction, submits a question, and verifies that the response appears on screen.

Because MSW intercepts the HTTP request, the test does not need a live AI service.

5. Test API failures

AI applications must handle unsuccessful requests gracefully.

Use a temporary MSW handler to simulate an unavailable service:

import { http, HttpResponse } from 'msw';
import { server } from '../test/server';

server.use(
  http.post('/api/ai/chat', () =>
    HttpResponse.json(
      { error: 'Service unavailable' },
      { status: 503 }
    )
  )
);

Use this handler in a separate test to verify that the component displays an error message and re-enables the submission button.

Other important scenarios include HTTP 429 rate limits, network failures, invalid response formats, timeouts, and retry behavior.

How to Mock Streaming LLM Responses

Many AI applications stream responses instead of waiting for the entire answer.

You can simulate a basic text stream with ReadableStream:

const stream = new ReadableStream({
  start(controller) {
    const encoder = new TextEncoder();

    controller.enqueue(encoder.encode('React '));
    controller.enqueue(encoder.encode('testing '));
    controller.enqueue(encoder.encode('made easier.'));

    controller.close();
  },
});

Use this stream in an MSW response when your application expects plain-text streaming.

For a production implementation, match the actual protocol. Server-sent events (SSE) and SDK-specific streams may require different framing and parsing.

Test whether partial responses appear in order, loading indicators disappear after completion, and interrupted streams are handled correctly.

How Five Technology Companies Approach AI Testing

Public engineering resources from these companies offer useful lessons. The examples below describe documented approaches and relevant engineering principles, not claims that every company uses the exact React testing stack demonstrated here.

1. GeekyAnts: Build testable AI products

GeekyAnts focuses on product engineering, including React development and AI-powered solutions.

Practical takeaway: Separate UI components from AI integrations, establish clear API contracts, and test loading, success, and error states independently. This makes AI features easier to maintain and test.

2. Microsoft: Simulate external dependencies

Microsoft’s developer guidance discusses testing API-dependent agent skills without repeatedly calling real services. Its developer article illustrates the value of API emulation and controlled responses.

Practical takeaway: Simulate API failures and dependency behavior to make tests reproducible and reduce unnecessary external requests.

3. Vercel: Mock model behavior

Vercel’s AI SDK testing documentation describes mock models and testing helpers for simulating language-model outputs.

Practical takeaway: Use model-level mocks for application logic built around the AI SDK, and HTTP mocks for React components that consume backend endpoints.

4. OpenAI: Evaluate actual model quality

OpenAI’s evaluation guide explains how to evaluate model outputs using test data and grading criteria.

Practical takeaway: A mocked response can verify that a React component displays text correctly, but it cannot establish factual accuracy. Use separate evaluations to measure real model quality.

5. Thoughtworks: Test edge cases and security

Thoughtworks’ published engineering practices for LLM applications discuss automated testing, adversarial testing, and responsible AI engineering.

Practical takeaway: Test unexpected inputs, malformed outputs, prompt-injection scenarios, and unsafe content handling—not just successful API responses.

Best Practices for Reliable React AI Testing

Follow these practices when building your test suite:

  1. Protect API keys: Keep provider credentials on the backend rather than exposing them in React code.
  2. Use realistic fixtures: Match your actual API response structure.
  3. Test failures: Include rate limits, network errors, and server failures.
  4. Isolate tests: Reset MSW handlers and mock state between tests.
  5. Test streaming separately: Verify incremental rendering and interrupted connections.
  6. Separate testing layers: Use component tests for UI behavior, integration tests for provider connectivity, and evaluations for model quality.
  7. Avoid unnecessary live calls: Reserve real-model tests for scenarios that genuinely require them.

Conclusion

Mocking LLM APIs makes React component testing faster, more predictable, and easier to maintain.

For most applications, Vitest, React Testing Library, and MSW provide a strong foundation. Applications using the Vercel AI SDK can also benefit from its model-testing utilities, while Playwright supports browser-level testing.

The key lesson from the engineering resources discussed above is that reliable AI development requires more than successful API requests. Developers must test application behavior, anticipate failures, protect security boundaries, and evaluate actual model outputs.