A middleware for the grunt-contrib-connect plugin that mocks a REST api with json-files from the filesystem. Makes it easy to develop and test your client code independent of the server.
This was originally forked from grunt-connect-apimock via the Express fork apimock-express.
Major differences from the original:
- Works with both Express and Connect (without specifically requiring Grunt).
- Supports both
.js
and.json
mocks. - Supports wildcards as the final path component.
- Improved and configurable logging.
- Helpers such as
defineMock
to assist IDE writing mocks. - Typescript support.
- Builtin Vite Plugin.
npm install --save-dev @forsakringskassan/apimock-express
const connect = require("connect");
const http = require("http");
const app = connect();
/* setup mocks */
apimock.config([
{ url: "/api/foo", dir: "tests/mock/foo" },
{ url: "/api/bar", dir: "tests/mock/bar" },
]);
/* install middleware */
server.middlewares.use("/", apimockExpress.mockRequest);
http.createServer(app).listen(3000);
const express = require("express");
const app = express();
/* setup mocks */
apimock.config([
{ url: "/api/foo", dir: "tests/mock/foo" },
{ url: "/api/bar", dir: "tests/mock/bar" },
]);
/* install middleware */
server.middlewares.use("/", apimockExpress.mockRequest);
app.listen(3000);
import { defineConfig } from "vite";
import { vitePlugin as apimockPlugin } from "@forsakringskassan/apimock-express";
export default defineConfig({
plugins: [
apimockPlugin([
{ url: "/api/foo", dir: "tests/mock/foo" },
{ url: "/api/bar", dir: "tests/mock/bar" },
]),
],
});
vue.config.js
const { defineConfig } = require("@vue/cli-service");
const apimock = require("@forsakringskassan/apimock-express");
apimock.config([
{ url: "/api/foo", dir: "tests/mock/foo" },
{ url: "/api/bar", dir: "tests/mock/bar" },
]);
module.exports = defineConfig({
devServer: {
before(app) {
/* install middleware */
app.use("*", apimock.mockRequest);
},
},
});
The mocked API consistst of a number of .js
or .json
files in a directory structure that represents the API.
E.g. with this configuration { "url": "/myApp/api/", "dir": "mymockdirectory" }
, then apimock works like this:
Method | Request | Filename |
---|---|---|
GET |
/myApp/api/users |
mymockdirectory/users.json |
POST |
/myApp/api/users |
mymockdirectory/users_post.json |
GET |
/myApp/api/users/1 |
mymockdirectory/users/1.json |
PUT |
/myApp/api/users/1 |
mymockdirectory/users/1_put.json |
DELETE |
/myApp/api/users/1 |
mymockdirectory/users/1_delete.json |
The format of the files can be in a simple or an advanced format.
- When using the simple format, the file content will be returned as the body of the response and http-status 200.
- When using the advanced format, it is possible to specify different responses and different http-status depending on the request parameters, body parameters, request headers or cookies of the request.
If a file with the format __default.json
exists in the folder, that one will be used if a specific file is not found.
Type: object
or array
of objects
An object containing the config of the apimock. See below. Can also be an array of objects if you want to mock different url:s to separate directories.
apimock.config([
{ url: "/api1/", dir: "test/api1" },
{ url: "/api2/", dir: "test/api2", delay: 500 },
]);
Type: String
Required: yes
The beginning of the url for your REST-api that you want to mock.
Type: String
Required: yes
The directory where your mock files for the apimock is located. The location is relative to the current working directory.
Type: Number
Required: no
Default value: 0
The base delay (in milliseconds) for all requests to this url, before the mock will respond.
The mock files can be written as either JSON or JS in a simple or an advanced format.
Use the simple format if it is ok to get the same response body and HTTP-status 200 for any request data.
If you need to get different responses or HTTP-status depending on the request parameters, the request body, the request headers or cookies use the advanced format.
This is simple. The content of the file will be returned as the body of the response with HTTP-status 200.
mymockdirectory/users.json
:
[
{ "userId": 1, "name": "Fred Flintstone" },
{ "userId": 2, "name": "Barney Rubble" }
]
The apimock will switch to advanced format if the object in the file has the variable responses
or/and the variable defaultResponse
on the root level that is != undefined.
If none of the variables are defined then the content is considered as simple format.
mymockdirectory/users.json
:
{
"responses": [
{
"request": {
"cookies": {
"myapi": "no-users"
}
},
"response": {
"status": 200,
"body": []
}
}
],
"defaultResponse": {
"status": 200,
"body": [
{ "userId": 1, "name": "Fred Flintstone" },
{ "userId": 2, "name": "Barney Rubble" }
]
}
}
Type: Object
Required: yes
The default response that will be retured if none of the requests in the responses array matches.
Type: Number
Required: no
Default value: 200
The HTTP-status.
Type: Object
Required: yes
The response body.
Type: Number
Required: no
Default value: 0
The delay in milliseconds before the mock will respond.
Type: Array
Required: no
An array of objects that contains the required request and the response that will be returned.
Type: Object
Required: yes
Describing the matching criteria.
Type: Object
Required: no
Names and values of the request parametes that needs to be matched for this response.
Type: Object
Required: no
Names and values of the request body parametes that needs to be matched for this response.
Type: Object
Required: no
Names and values of the request headers parametes that needs to be matched for this response.
Type: Object
Required: no
Names and values of the request cookies that needs to be matched for this response.
Type: Object
Required: yes
Describing the response that will be retured if the request matches.
Type: Number
Required: no
Default value: 200
The HTTP-status.
Type: Object
Required: yes
The response body.
Type: Number
Required: no
Default value: 0
The delay in milliseconds before the mock will respond.
Different responses depending on the request parameters:
{
"responses": [
{
"request": {
"parameters": {
"foo": "bar",
"bar": "foo"
}
},
"response": {
"status": 401,
"body": {
"message": "Two parameters matches"
}
}
},
{
"request": {
"parameters": {
"foo": "bar"
}
},
"response": {
"status": 402,
"body": {
"message": "One parameter matches"
}
}
}
],
"defaultResponse": {
"status": 201,
"body": {
"message": "Nothing matches. Default response"
}
}
}
Different responses depending on the request body:
{
"responses": [
{
"request": {
"body": {
"user": { "firstname": "Luke", "lastname": "Skywalker" }
}
},
"response": {
"status": 403,
"body": {
"message": "Two body parameters matches"
}
}
},
{
"request": {
"body": {
"foo": "bar"
}
},
"response": {
"status": 404,
"body": {
"message": "One body parameter matches"
}
}
}
],
"defaultResponse": {
"status": 201,
"body": {
"message": "Nothing matches. Default response"
}
}
}
A combination of request parameter and request body
{
"responses": [
{
"request": {
"parameters": {
"foo": "bar"
},
"body": {
"bar": "foo"
}
},
"response": {
"status": 400,
"body": {
"message": "Both parameter and body matches"
}
}
}
],
"defaultResponse": {
"status": 201,
"body": {
"message": "Nothing matches. Default response"
}
}
}
Different responses depending on the request headers:
{
"responses": [
{
"request": {
"headers": {
"header1": "one",
"header2": "two"
}
},
"response": {
"status": 401,
"body": {
"message": "When the headers header1=one and header2=two"
}
}
}
],
"defaultResponse": {
"status": 201,
"body": {
"message": "Nothing matches. Default response"
}
}
}
Different responses depending on the request cookies:
{
"responses": [
{
"request": {
"cookies": {
"foo": "foo"
}
},
"response": {
"status": 400,
"body": {
"message": "When cookie foo=foo"
}
}
}
],
"defaultResponse": {
"status": 201,
"body": {
"message": "Nothing matches. Default response"
}
}
}
Delaying a response:
{
"responses": [
{
"request": {
"parameters": {
"foo": "foo"
}
},
"response": {
"status": 200,
"body": {
"message": "Delayed 500 milliseconds"
},
"delay": 500
}
}
],
"defaultResponse": {
"status": 200,
"body": {
"message": "Delayed 1000 milliseconds"
},
"delay": 1000
}
}
For more examples see the tests in test/