5.1 KiB
MSW (Mock Service Worker) Setup Guide
FE-API-019: API Mocking for Development
This guide explains how to use MSW (Mock Service Worker) for API mocking during development and testing.
Overview
MSW allows you to intercept and mock HTTP requests at the network level, making it perfect for:
- Development without a running backend
- Testing with consistent mock data
- Simulating error scenarios
- Testing offline behavior
Configuration
Environment Variable
MSW is controlled by the VITE_USE_MSW environment variable:
# Enable MSW
VITE_USE_MSW=1 npm run dev
# Or use the dedicated script
npm run dev:mocks
# Disable MSW (default)
VITE_USE_MSW=0 npm run dev
Initialization
MSW is automatically initialized in main.tsx when:
VITE_USE_MSWis set to1ortrue- Running in development mode (
import.meta.env.DEV)
The worker is started before the React app renders to ensure all requests are intercepted.
File Structure
apps/web/src/mocks/
├── handlers.ts # Mock request handlers
├── browser.ts # Browser worker setup
├── node.ts # Node.js server setup (for tests)
├── index.ts # Exports
└── test-setup.ts # Test configuration
Adding New Handlers
Edit apps/web/src/mocks/handlers.ts to add new mock handlers:
import { http, HttpResponse } from 'msw';
export const handlers = [
// GET request
http.get('/api/v1/endpoint', () => {
return HttpResponse.json({
data: {
/* mock data */
},
});
}),
// POST request with body
http.post('/api/v1/endpoint', async ({ request }) => {
const body = await request.json();
return HttpResponse.json(
{
data: {
/* response */
},
},
{ status: 201 },
);
}),
// Request with parameters
http.get('/api/v1/endpoint/:id', ({ params }) => {
const { id } = params;
return HttpResponse.json({
data: { id /* ... */ },
});
}),
// Request with query parameters
http.get('/api/v1/endpoint', ({ request }) => {
const url = new URL(request.url);
const param = url.searchParams.get('param');
return HttpResponse.json({
data: { param /* ... */ },
});
}),
// Error response
http.get('/api/v1/error', () => {
return HttpResponse.json(
{ error: 'Something went wrong' },
{ status: 500 },
);
}),
];
URL Matching
Important: MSW handlers must match the full URL path that the client sends.
Since apiClient uses baseURL: env.API_URL (e.g., http://127.0.0.1:8080/api/v1), handlers should match:
- ✅
/api/v1/roles(matches full path) - ✅
http://127.0.0.1:8080/api/v1/roles(matches full URL) - ❌
/roles(won't match if baseURL is set)
However, MSW can match relative paths if configured correctly. The current setup uses relative paths like /api/v1/*.
Current Handlers
The following endpoints are currently mocked:
Authentication
POST /api/auth/loginPOST /api/auth/registerPOST /api/auth/refreshGET /api/users/profilePUT /api/users/profile
Chat
GET /api/chat/conversationsGET /api/chat/conversations/:id/messagesPOST /api/chat/conversations/:id/messages
Library
GET /api/library/tracksPOST /api/library/tracks
Health & Errors
GET /api/healthGET /api/error/500GET /api/error/404GET /api/error/timeout
Testing with MSW
In Unit Tests
import { server } from '@/mocks/test-setup';
import { handlers, errorHandlers } from '@/mocks/handlers';
beforeAll(() => {
server.listen();
});
afterEach(() => {
server.resetHandlers();
});
afterAll(() => {
server.close();
});
// Use error handlers for error scenarios
test('handles error', () => {
server.use(...errorHandlers);
// Test error handling
});
In E2E Tests
# Run E2E tests with MSW
npm run test:e2e:msw
Best Practices
- Keep handlers realistic: Mock data should match the real API structure
- Use variables: Store mock data in constants for reusability
- Handle edge cases: Add handlers for error scenarios (400, 401, 500, etc.)
- Document changes: Update this guide when adding new handlers
- Test both paths: Test with MSW enabled and disabled
Troubleshooting
MSW not intercepting requests
- Check that
VITE_USE_MSW=1is set - Verify
mockServiceWorker.jsexists inpublic/ - Check browser console for MSW initialization messages
- Ensure handlers match the exact URL path
Handler not matching
- Check the exact URL being sent (check Network tab)
- Verify the handler path matches exactly
- Use
onUnhandledRequest: 'warn'to see unmatched requests
Service Worker issues
- Clear browser cache and service workers
- Unregister old service workers in DevTools > Application > Service Workers
- Restart the dev server
Updating Mock Service Worker
If MSW version is updated, regenerate the service worker:
npx msw init public/ --save