Mock Server

A fake server that simulates API responses for testing and development purposes.

A mock server is a fake API server that simulates the behavior of a real backend. Instead of connecting to actual databases or services, it returns predefined responses based on the requests it receives. Mock servers are essential for frontend development, testing, and demos when the real API isn't available, isn't stable, or would be expensive to call.

Why Use a Mock Server?

Parallel development: Frontend and backend teams can work simultaneously. Don't wait for the API to be ready - mock it based on the agreed contract and start building the UI immediately.

Reliable testing: Real APIs are unpredictable - they timeout, rate limit, return different data, or go down. Mock servers return exactly what you configure, every time. This makes tests deterministic.

Cost savings: Third-party APIs charge per request. Stripe, Twilio, AWS - running tests against them costs money. Mock servers are free to call thousands of times.

Edge case testing: How does your app handle a 500 error? A 3-second delay? An empty response? Mock servers let you simulate conditions that are hard to reproduce with real APIs.

Offline development: Work on the plane, at a café with bad WiFi, or when the staging server is down. Mock servers run locally with zero external dependencies.

Types of Mock Servers

TypeDescriptionBest For
StaticReturns fixed JSON filesSimple demos, early prototyping
DynamicGenerates responses based on requestRealistic testing, variable data
Record/ReplayRecords real API calls, replays themIntegration testing, capturing edge cases
Contract-basedGenerated from OpenAPI/Swagger specAPI-first development

Static vs Dynamic Mocking

Static mocking returns the same response every time:

  • GET /users → always returns users.json
  • Simple but limited - can't test pagination, search, or CRUD

Dynamic mocking generates responses based on the request:

  • GET /users/123 → returns user with id: 123
  • POST /users → echoes back sent data with generated id
  • GET /users?search=john → filters the mock data

Setting Up a Mock Server

Standalone tools:

  • json-server: Zero-config REST API from a JSON file
  • Prism: Mock server from OpenAPI spec
  • WireMock: Powerful Java-based mock server
  • MockServer: Supports complex scenarios and verification

In-app mocking:

  • MSW (Mock Service Worker): Intercepts requests at network level
  • Mirage JS: In-browser server for frontend apps
  • nock: HTTP mocking for Node.js tests

Key Features to Look For

Request matching: Match requests by URL, method, headers, query params, or body content. The more flexible, the better.

Response templating: Generate dynamic responses using request data: /users/{{id}} returns {id: {{id}}, ...}

Delay simulation: Add artificial latency to test loading states and timeouts.

Stateful behavior: Remember previous requests. POST creates a user, subsequent GET returns it.

Verification: Assert that specific requests were made with expected parameters.

Common Patterns

1. Happy path baseline: Start with successful responses for all endpoints. This is your default state.

2. Error scenarios: Create separate configurations for error cases: auth failures, validation errors, server errors.

3. Slow responses: Add 2-5 second delays to test loading states, spinners, and timeout handling.

4. Empty states: Return empty arrays and null values to test "no data" UI states.

5. Large datasets: Generate hundreds of items to test pagination, virtual scrolling, and performance.

Best Practices

Keep mocks close to reality: Your mock responses should match the real API structure exactly. If they drift apart, you'll have bugs when switching to the real API.

Version your mocks: When the API changes, update the mocks. Keep them in sync with your OpenAPI spec.

Don't over-mock: Mock external dependencies, not your own code. If you're mocking everything, you're not testing anything.

Use realistic data: {name: "Test User"} is fine for unit tests. For demos and E2E tests, use realistic fake data with proper names, emails, and addresses.

Document mock behavior: Note any differences between mock and real API. If the mock simplifies something, document it so nobody is surprised later.

Code Examples

MSW (Mock Service Worker) Setup

// handlers.js - Define mock API handlers
import { http, HttpResponse } from 'msw';

export const handlers = [
  // List users
  http.get('/api/users', () => {
    return HttpResponse.json([
      { id: 1, name: 'John Doe', email: 'john@example.com' },
      { id: 2, name: 'Jane Smith', email: 'jane@example.com' },
    ]);
  }),

  // Get user by ID
  http.get('/api/users/:id', ({ params }) => {
    return HttpResponse.json({
      id: Number(params.id),
      name: 'John Doe',
      email: 'john@example.com',
    });
  }),

  // Create user (echo back with ID)
  http.post('/api/users', async ({ request }) => {
    const body = await request.json();
    return HttpResponse.json(
      { id: Date.now(), ...body },
      { status: 201 }
    );
  }),

  // Simulate error
  http.delete('/api/users/:id', () => {
    return HttpResponse.json(
      { error: 'Unauthorized' },
      { status: 401 }
    );
  }),
];