·8 min read
Mocking REST APIs with JSON Fixtures
Frontend blocked on a backend that doesn't exist yet? Mock your APIs. This guide covers MSW, json-server, and fixture strategies using sample JSON files for users, products, and nested objects.
Why mock instead of wait
- Frontend and backend work in parallel, not sequentially
- Reproducible test fixtures for E2E and CI
- Demo environments that don't depend on infra
- Offline development
Option 1: MSW (Mock Service Worker)
Intercepts fetch/XHR at the network layer. Your app code stays unchanged.
import { http, HttpResponse } from 'msw';
import { setupWorker } from 'msw/browser';
import users from './users.json';
const handlers = [
http.get('/api/users', () => HttpResponse.json(users)),
http.get('/api/users/:id', ({ params }) => {
const user = users.find((u) => u.id === Number(params.id));
return user
? HttpResponse.json(user)
: new HttpResponse(null, { status: 404 });
}),
http.post('/api/users', async ({ request }) => {
const body = await request.json();
return HttpResponse.json({ id: users.length + 1, ...body }, { status: 201 });
}),
];
const worker = setupWorker(...handlers);
worker.start();
Option 2: json-server (zero-config CRUD)
# Download sample data from /data/json
curl -o db.json https://example.com/users-sample.json
npx json-server db.json --port 3001
# Get GET /users, POST /users, PATCH /users/1 — all working
Perfect for quick prototypes. Supports pagination, filtering, sorting, and full CRUD with zero code.
Sample fixtures
Download from our data library:
- Sample JSON files — users, products, GeoJSON
- XML samples — for SOAP or RSS mocking
- CSV data — easy to convert to JSON with pandas
Pattern: typed fixtures
// fixtures/users.ts
export interface User {
id: number;
email: string;
name: string;
role: 'admin' | 'user';
}
export const users: User[] = [
{ id: 1, email: '[email protected]', name: 'Alice', role: 'admin' },
{ id: 2, email: '[email protected]', name: 'Bob', role: 'user' },
];
Type-safe fixtures mean your mocks stay aligned with your domain model. Rename a field in the User type, TypeScript flags every fixture that needs updating.
Testing error states
// Simulate 500 error
http.get('/api/flaky', () => {
return new HttpResponse(null, { status: 500 });
}),
// Simulate slow network
http.get('/api/slow', async () => {
await new Promise((r) => setTimeout(r, 3000));
return HttpResponse.json({ ok: true });
}),
Scope: mocks for dev and tests, never prod
- Disable MSW in production builds
- Gate via env var:
if (process.env.NEXT_PUBLIC_MOCK) worker.start() - Use real APIs in staging to catch integration bugs early
Related
For database-side mocking, see database seeding from SQL dumps. For general JSON samples, read sample JSON data for API testing.