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.
Mock Server
A fake server that simulates API responses for testing and development purposes.
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
| Type | Description | Best For |
|---|---|---|
| Static | Returns fixed JSON files | Simple demos, early prototyping |
| Dynamic | Generates responses based on request | Realistic testing, variable data |
| Record/Replay | Records real API calls, replays them | Integration testing, capturing edge cases |
| Contract-based | Generated from OpenAPI/Swagger spec | API-first development |
Static vs Dynamic Mocking
Static mocking returns the same response every time:
GET /users→ always returnsusers.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: 123POST /users→ echoes back sent data with generated idGET /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 }
);
}),
];Related Terms
API Mocking
Simulating API behavior to enable development and testing without real backend services.
Rate Limiting
A technique to control the number of API requests a client can make within a time window.
Contract Testing
A testing approach that verifies API consumers and providers adhere to a shared contract, ensuring integration compatibility.
HTTP Status Codes
Standard response codes that indicate the result of an HTTP request.