API Mocking — Complete Guide to Simulated Endpoints
In this tutorial, you will learn about API Mocking. We cover key concepts, practical examples, and best practices to help you master this topic.
API mocking creates simulated endpoints that return realistic responses without a real backend, enabling parallel development, testing, and demos before the actual API is built.
What You'll Learn
- Benefits of API mocking for development speed
- Creating mock servers from OpenAPI specs
- Dynamic mock responses with realistic data
Why It Matters
Frontend development often blocks on backend API availability. Mocking removes this dependency, allowing frontend and backend teams to work in parallel against agreed contracts.
Real-World Use
Durga Antivirus Pro frontend team develops against mock API servers generated from OpenAPI contracts. By the time the backend is ready, the frontend is fully tested against the contract, catching integration issues early.
flowchart LR
C["OpenAPI Contract"] --> M["Mock Server"]
F["Frontend Team"] --> M
B["Backend Team"] --> C
M --> R["Realistic Responses"]
M --> E["Error Scenarios"]
M --> D["Edge Cases"]
style M fill:#dbeafe,stroke:#2563eb
Code Examples
# Mock server from OpenAPI spec using prism
# Install: npm install -g @stoplight/prism-cli
# Run: prism mock openapi.yaml
# Example mock server behavior:
# GET /api/threats -> returns realistic threat list
# GET /api/threats/1 -> returns single threat
# GET /api/threats/999 -> returns 404 (dynamic)
Expected output: Prism mock server responds to all defined endpoints with example data from the spec.
# Custom mock server with Flask
from flask import Flask, jsonify, request
from faker import Faker
app = Flask(__name__)
fake = Faker()
def generate_threat():
return {
'id': fake.uuid4()[:8],
'name': fake.catch_phrase(),
'severity': fake.random_element(['low', 'medium', 'high', 'critical']),
'discovered_at': fake.iso8601(),
'status': fake.random_element(['active', 'contained', 'resolved']),
}
@app.route('/api/threats', methods=['GET'])
def list_threats():
page = int(request.args.get('page', 1))
count = int(request.args.get('count', 20))
threats = [generate_threat() for _ in range(count)]
return jsonify({
'data': threats,
'meta': {'page': page, 'count': count, 'total': 1000}
})
@app.route('/api/threats/<id>', methods=['GET'])
def get_threat(id):
threat = generate_threat()
threat['id'] = id
return jsonify({'data': threat})
if __name__ == '__main__':
app.run(port=4010)
Expected output: Mock server returns realistic, varied data for development and testing.
// Dynamic mock with conditional responses
const express = require('express');
const app = express();
const scenarios = {
success: { status: 200, body: { status: 'paid' } },
pending: { status: 200, body: { status: 'pending' } },
failed: { status: 402, body: { error: 'payment_failed', message: 'Card declined' } },
timeout: { status: 504, body: { error: 'timeout' } },
};
app.post('/api/payments', (req, res) => {
const scenario = req.headers['x-mock-scenario'] || 'success';
const mock = scenarios[scenario] || scenarios.success;
res.status(mock.status).json(mock.body);
});
// Simulate latency
app.use((req, res, next) => {
const delay = parseInt(req.headers['x-mock-delay']) || 0;
setTimeout(next, delay);
});
app.listen(4010);
Expected output: Mock server returns different scenarios based on request headers, allowing testing of success and failure paths.
Common Mistakes
1. Mock Data That Is Too Perfect
Real APIs return inconsistent data (null fields, varying lengths). Realistic mock data catches frontend edge cases.
2. Only Mocking Success Responses
Testing only happy paths with mocks misses error handling bugs. Mock all error scenarios.
3. Mock Drift from Real API
As the real API evolves, mocks become outdated. Regenerate mocks from the OpenAPI contract on every change.
4. No Latency Simulation
Real APIs have latency. Mocking instant responses hides performance issues. Add configurable delays.
5. Mocking Third-Party APIs Without Auth
If the real API requires auth, the mock should too. Otherwise, integration tests fail when switching to real.
Practice Questions
- How does API mocking accelerate development?
- Why should mock data be realistic rather than perfect?
- What is the risk of only mocking success responses?
- How do you prevent mock drift from the real API?
- Why should mocks simulate latency?
Answers:
- Mocking removes the backend dependency, letting frontend and backend teams work in parallel.
- Perfect mock data hides edge cases that occur with real data (nulls, empty strings, unexpected formats).
- Error handling code remains untested until production, when errors cause crashes.
- Generate mocks from the same OpenAPI contract that defines the real API.
- Real APIs have network and processing latency; mocks without latency hide performance issues.
Challenge: Build a mock server for a payment API that supports multiple scenarios via headers: success, card_declined, insufficient_funds, timeout, and server_error. Include configurable latency (0ms-5000ms) and realistic response data.
FAQ
Mini Project
Build a mock server for a user management API (CRUD operations) using Flask or Express. Generate realistic mock data, support error scenarios via headers, simulate 100-500ms random latency, and validate requests against a simple schema.
What's Next
Explore API testing strategies using mock servers, or learn about API contracts for generating mocks from formal specifications.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro