A powerful HTTP mock interceptor for Angular applications that helps you simulate API responses during development and testing.
- 🚀 Easy to set up and use
- 🎯 Path matching with typed parameters support
- 📝 Query parameters and headers matching
- ⏱️ Configurable response delays
- 🔄 Counter-based responses
- 🎮 Full control over mock responses
- 📦 Mock data factory
- 🔄 Progress events simulation
- 📁 File download simulation
npm i ngx-api-mocks-interceptor
- Create and Import the interceptor in your app.config.ts:
ng g interceptor mockInterceptor
import { HttpInterceptorFn } from "@angular/common/http";
export const mockInterceptor: HttpInterceptorFn = (req, next) => {
return next(req);
};
export const appConfig: ApplicationConfig = {
providers: [provideHttpClient(withInterceptors([mockInterceptor]))],
};
- Create your mock data using the factory:
import { autoIncrement, boolean, mocks, lorem, array, literal } from "ngx-api-mocks-interceptor";
import { faker } from "@faker-js/faker";
interface Todo {
id: number;
label: string;
description: string;
completed: boolean;
status: 'OPEN' | 'CLOSE' | 'WAITING';
options: {
id: number;
name: string;
}[];
}
// Create several mocks with the `mocks` factory
export const todosMock = mocks<Todo>(
{
id: autoIncrement(1),
label: () => faker.lorem.words(3), // We can use faker or any other generator
description: lorem(6),
completed: boolean(0.3),
status: literal(['OPEN', 'CLOSE', 'WAITING'])
options: array({
id: autoIncrement(1),
name: value('foo'),
}, {count: 2}),
},
{
count: 10, // Generate 10 items
}
);
// Or a single mock with the `mock` factory
export const todoMock = mock<Todo>({
id: autoIncrement(1),
label: () => faker.lorem.words(3),
description: lorem(6),
completed: boolean(0.3),
status: literal(['OPEN', 'WAITING'])
options: array({
id: autoIncrement(1),
name: value('foo'),
}, { min: 2, max: 5 }),
});
- Configure your mock interceptor:
import { match, mockRouter } from "ngx-api-mocks-interceptor";
export const mockInterceptor: HttpInterceptorFn = (req, next) => {
const endpoint = "http://localhost:3000/api/v1";
return mockRouter(req, next, {
delay: 1000,
pathMatch: "full",
routes: [
match(`${endpoint}/api/todos/`, "GET", () => new HttpResponse({ status: 200, body: todosMock.value })),
match(`${endpoint}/api/todos/:id`, "GET", (_, params) => {
const todo = todosMock.get((todo) => todo.id === +params.id);
return new HttpResponse({ status: 200, body: todo });
}),
match(
`${endpoint}/api/todos`,
"POST",
(req: HttpRequest<Partial<Todo>>) =>
new HttpResponse({
status: 201,
body: todosMock.add(req.body!),
})
),
],
// Handle unmatched routes
onNoMatch: () => of(new HttpResponse({ status: 404, body: { error: "Not Found" } })),
});
};
- Advenced configuration:
import { createRouteCounter, match, mockRouter, createFileMockResponse } from "ngx-api-mocks-interceptor";
const getItemCounter = createRouteCounter();
export const mockInterceptor: HttpInterceptorFn = (req, next) => {
const endpoint = "http://localhost:3000/api/v1";
return mockRouter(req, next, {
delay: 1000, // Global delay
pathMatch: "full",
routes: [
match(
`${endpoint}/api/todos`,
"GET",
() =>
new HttpResponse({
status: 200,
body: todosMock.value,
}),
{
delay: 800,
counter: getItemCounter,
responses: [
{
count: "2n", // Every second request
response: () =>
new HttpResponse({
status: 429,
body: { error: "Rate limited" },
}),
},
{
count: ">5", // After 5 requests
response: () =>
new HttpResponse({
status: 503,
body: { error: "Service degraded" },
}),
},
],
}
),
// GET with path parameters
match(`${endpoint}/api/todos/:id`, "GET", (_, params) => {
const todo = todosMock.get((todo) => todo.id === +params.id);
return new HttpResponse({ status: 200, body: todo });
}),
// POST with request body
match(
`${endpoint}/api/todos`,
"POST",
(req: HttpRequest<Partial<Todo>>) =>
new HttpResponse({
status: 201,
body: todosMock.add(req.body!),
})
),
// File download simulation
match(`${endpoint}/api/todos/download`, "GET", () =>
createFileMockResponse({
path: "/mocks/example.txt",
filename: "todos.txt",
contentType: "text/plain",
headers: {
"Cache-Control": "no-cache",
},
chunkDelay: 200,
})
),
// Upload progress simulation
match(`${endpoint}/api/upload`, "POST", () => [
{
type: HttpEventType.UploadProgress,
loaded: 0,
total: 100,
},
{
type: HttpEventType.UploadProgress,
loaded: 50,
total: 100,
},
new HttpResponse({
status: 200,
body: { message: "Upload complete" },
}),
]),
],
// Handle unmatched routes
onNoMatch: () =>
of(
new HttpResponse({
status: 404,
body: { error: "Not Found" },
})
),
});
};
We welcome contributions! Please see our Contributing Guide for details.
This project is licensed under the MIT License - see the LICENSE file for details.