Http API mock router for express application
npm i mockit-express express body-parser
# to enable yaml file format support
npm i js-yaml
# to enable faker support
npm i faker
# to enable proxy support
npm i express-request-proxy
# to enable file watching and auto-reload support
npm i chokidar
# to enable nock support
npm i -D nock
const mockit = require("mockit-express");
const router = mockit("/path/routes/config/file");
app.use("/api/v1", router);
Watch config file change and reload automatically
const router = mockit("/path/routes/config/file", (err, changed) => {
if (err) {
console.error("failed to load config file", err);
} else if (changed) {
console.log("file changed");
} else {
console.warn("file removed");
}
});
Pass routes directly
const router = mockit({ "GET /api/v1/account": { code: 200 } });
Use db instance
const db = new mockit.Database();
db.load("/path/routes/config/file");
const router = mockit(db);
routes.yml
# method and path
GET /api/v1/account:
# bypass(disable) this route(optional)
bypass: false
# simulate response delay in milliseconds(optional)
delay: 1000
# http status code
code: 200
# response headers(optional)
headers:
Content-Type: "application/json"
Server: "Nginx"
# response body(string)(optional)
body: |-
{
"name": "admin"
}
PUT /api/v1/account:
bypass: false
delay: 0
code: 204
headers:
Content-Type: "application/json"
Server: "Nginx"
# match all methods and sub paths
ALL /api/v1/proxy/*:
# reverse proxy
proxy:
# proxy remote
remote: "https://jsonplaceholder.typicode.com"
# rewrite rules in nginx style(optional)
rewrite: ^/api/v1/proxy/(.*) /posts/$1
# proxy headers(optional)
headers:
# see Proxy Header Variables for details
X-Real-IP: $remote_addr
X-Forwarded-For: $proxy_add_x_forwarded_for
X-Mockit-Proxy: true
Upgrade: $http_upgrade
User-Agent: $http_user_agent
Connection: "upgrade"
Host: $host
# using params in url
GET /api/v1/users/:id:
code: 404
headers:
Content-Type: "application/json"
body: |-
{
"id": 0,
"name": "unknown"
}
# using conditions
cond:
- case: params.id == 1
code: 200
body: |-
{
"id": 1,
"name": "Alfonzo"
}
- case: params.id == 2
code: 200
body: |-
{
"id": 2
"name": "Juanita"
}
GET /api/v1/members/:id:
code: 200
headers:
Content-Type: "application/json"
# see Interpolation for details
body: |-
{
"index": ${params.id},
"uid": ${faker.random.number() + params.id},
"name": "${faker.internet.userName()}",
"fullname": "${faker('zh_CN').name.firstName}${faker('zh_CN').name.lastName()}"
"email": "${faker.internet.email}",
"location": {
"latitude": ${faker.address.latitude},
"longitude": ${faker.address.longitude}
},
"desc": "${faker.lorem.paragraph}",
"escape": "${'\{' + 'using curly braces inside interpo template' + '\}'}"
}
routes.json
{
"GET /api/v1/account": {
"bypass": false,
"delay": 1000,
"code": 200,
"headers": {
"Content-Type": "application/json",
"Server": "Nginx"
},
"body": "{\"name\":\"admin\"}"
},
"PUT /api/v1/account": {
"bypass": false,
"delay": 0,
"code": 200,
"headers": {
"Content-Type": "application/json",
"Server": "Nginx"
}
},
"ALL /api/v1/proxy/*": {
"proxy": {
"remote": "https://jsonplaceholder.typicode.com",
"rewrite": "^/api/v1/proxy/(.*) /posts/$1",
"headers": {
"X-Real-IP": "$remote_addr",
"X-Forwarded-For": "$proxy_add_x_forwarded_for",
"X-Mockit-Proxy": true,
"Upgrade": "$http_upgrade",
"User-Agent": "$http_user_agent",
"Connection": "upgrade",
"Host": "$host"
}
}
},
"GET /api/v1/users/:id": {
"code": 200,
"headers": {
"Content-Type": "application/json"
},
"body": "{\"id\":0,\"name\":\"unknown\"}",
"cond": [
{
"case": "params.id == 1",
"body": "{\"id\":1,\"name\":\"Alfonzo\"}"
},
{
"case": "params.id == 2",
"body": "{\"id\":2,\"name\":\"Juanita\"}"
}
]
},
"GET /api/v1/members/:id": {
"code": 200,
"headers": {
"Content-Type": "application/json"
},
"body": "{\"index\":${params.id},\"uid\":${faker.random.number() + params.id},\"name\":\"${faker.internet.userName()}\",\"fullname\":\"${faker(\"zh_CN\").name.firstName}${faker(\"zh_CN\").name.lastName()}\",\"email\":\"${faker.internet.email}\",\"location\": {\"latitude\":${faker.address.latitude},\"longitude\":${faker.address.longitude}},\"desc\":\"${faker.lorem.paragraph}\",\"escape\":\"${'\\{' + 'using curly braces inside interpo template' + '\\}'}\"}"
}
}
$host
Proxy remote host name
$remote_addr
Client request IP
$proxy_add_x_forwarded_for
Concat client X-Forwarded-For
header(if exists) with Client IP
$http_{name}
Request header field in snakecase
e.g.
$http_user_agent
returns client header User-Agent
Expressions encaptured by ${
and }
in body
field will be interpolated.
Basic
"${'string field'}"
=> "string field"
${1 + 1}
=> 2
"${'\{using curly braces inside interpolation\}'}"
=> "{using curly braces inside interpolation}"
Accessing params
, query
, body
and headers
params
keeps the passed-in parameters in route url,query
stores request query string values,body
andheaders
hold request body and headers respectively
Definition: /api/v1/items/:id
Request URL: /api/v1/items/12?color=red
Request Headers: {'x-version':'1.31'}
Request body: '{"count": 9}'
${params.id}
=> 12
${query.color}
=> "red"
${body.data}
=> {"count": 9}
${headers['x-version']}
=> "1.31"
Faking data
faker
is a thirdparty library
${faker.random.number()}
=> 1289
${faker.random.number}
=> 4096
the first example calls a function and returns the result
the second example returns a function which will be called without context
"${faker.name.firstName}"
=> "James"
$faker
is an additional function which can be called to use a specific locale(for the current context only)
"${$faker('zh_CN').name.firstName}"
=> "朱"
see faker for reference
npm test
const mockit = require("mockit-express");
//...
module.exports = {
//...
devServer: {
after: function(app) {
app.use(mockit("/path/routes/file"));
}
}
};
Proxy routes and routes with params are not supported when using nock. 'ALL' method is also forbidden
load a file
const nockit = require("mockit-express/nock");
const scope = nockit("http://domain.com", "/path/to/routes/file");
// alias for nock.cleanAll()
scope.stop();
// alias for nock.restore()
scope.pause();
// alias for nock.activate()
scope.activate();
Load existing data
nockit("http://domain.com", db);
nockit("http://domain.com", {
"GET /api/v1/test": {
code: 200,
delay: 1000,
body: "success"
}
});
Add to exising nock scope
nockit.mount(scope, route);
See mockit
See License