@forsakringskassan/apimock-express

中文文档
4.4.0发布于 2026/11/06MITTypeScriptESM + CJS零依赖构建来源已验证近 30 天下载 2.9万

Express middleware for mocking API calls with json & js files during development.

原始使用文档
文档目录22 节
  1. Usage
  2. With Connect
  3. With Express
  4. With Vite
  5. With Vue CLI
  6. Mock file and directory structure
  7. Directories
  8. Wildcard / global file
  9. Mock Configuration
  10. apimock.config
  11. File format
  12. Simple format
  13. Advanced format
  14. Examples
  15. Using Helpers
  16. More Examples
  17. Inline mocks
  18. Basic inline mock
  19. Mixing inline and file-based mocks
  20. Inline mocks with conditional responses
  21. Browser mode (MSW)
  22. Browser mode (manual)

@forsakringskassan/apimock-express

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 .mjs/.cjs/.js/.ts/.mts 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.

Usage

npm install --save-dev @forsakringskassan/apimock-express

With Connect

const apimock = require("@forsakringskassan/apimock-express");
const http = require("http");
const connect = require("connect");

const app = connect();

/* setup mocks */
apimock.config([
    { url: "/api/foo", dir: "tests/mock/foo" },
    { url: "/api/bar", dir: "tests/mock/bar" },
]);

/* install middleware */
app.use("/", apimock.mockRequest);

http.createServer(app).listen(3000);

With Express

const apimock = require("@forsakringskassan/apimock-express");
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 */
app.use("/", apimock.mockRequest);

app.listen(3000);

With Vite

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" },
        ]),
    ],
});

With Vue CLI

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);
        },
    },
});

Mock file and directory structure

The mocked API consistst of a number of .mjs/.cjs/.js/.ts/.mts 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:

MethodRequestFilename
GET/myApp/api/usersmymockdirectory/users.json
POST/myApp/api/usersmymockdirectory/users_post.json
GET/myApp/api/users/1mymockdirectory/users/1.json
PUT/myApp/api/users/1mymockdirectory/users/1_put.json
DELETE/myApp/api/users/1mymockdirectory/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.

Directories

If the mock is a directory it can contain __${method}.{js,json} instead, for instance given the following configuration:

{
    "url": "/myApp/api/foo",
    "dir": "mymockdirectory/foo"
}

when mymockdirectory/foo is a directory the requests are mapped like this:

MethodRequestFilename
GET/myApp/api/foomymockdirectory/foo/__get.json
POST/myApp/api/foomymockdirectory/foo/__post.json

This is mostly useful when the API under mock does not have a prefix and we do not want to apply / as the mock url.

Wildcard / global file

If a file with the format __default.json exists in the folder, that one will be used if a specific file is not found.

Mock Configuration

apimock.config

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 },
]);

url

Type: String

Required: yes

The beginning of the url for your REST-api that you want to mock.

dir

Type: String

Required: yes

The directory where your mock files for the apimock is located. The location is relative to the current working directory.

delay

Type: Number

Required: no

Default value: 0

The base delay (in milliseconds) for all requests to this url, before the mock will respond.

File format

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.

Simple 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" }
]

Advanced format

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" }
        ]
    }
}

defaultResponse

Type: Object

Required: yes

The default response that will be retured if none of the requests in the responses array matches.

defaultResponse.status

Type: Number

Required: no

Default value: 200

The HTTP-status.

defaultResponse.body

Type: Object

Required: yes

The response body.

defaultResponse.delay

Type: Number

Required: no

Default value: 0

The delay in milliseconds before the mock will respond.

responses

Type: Array

Required: no

An array of objects that contains the required request and the response that will be returned.

responses.request

Type: Object

Required: yes

Describing the matching criteria.

responses.request.parameters

Type: Object

Required: no

Names and values of the request parametes that needs to be matched for this response.

responses.request.body

Type: Object

Required: no

Names and values of the request body parametes that needs to be matched for this response.

responses.request.headers

Type: Object

Required: no

Names and values of the request headers parametes that needs to be matched for this response.

responses.request.cookies

Type: Object

Required: no

Names and values of the request cookies that needs to be matched for this response.

responses.response

Type: Object

Required: yes

Describing the response that will be retured if the request matches.

responses.response.status

Type: Number

Required: no

Default value: 200

The HTTP-status.

responses.response.body

Type: Object

Required: yes

The response body.

responses.response.delay

Type: Number

Required: no

Default value: 0

The delay in milliseconds before the mock will respond.

Examples

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
    }
}

Using Helpers

It is often simpler to setup mocks using the provided helper functions.

The createMockByCookie(...) Helper Function

The createMockByCookie(...) helper function sets up mock responses according to a specific cookie. If used correctly, Typescript can also help to provide type safety for the cookie and its possible values.

import {
    createMockByCookie,
    type MockCookieValue,
} from "@forsakringskassan/apimock-express/helpers";

interface MyResponseType {
    message: string;
}

export const getSomethingMockCookie = {
    name: "api-get-something",
    values: {
        foo: "foo-200",
        bar: "bar-200",
        foobar: "foobar-500",
    },
} as const; // { ... } as const is important to get proper type safety

// The type below can also be used by consumer for getting the cookie name and its possible values
export type GetSomethingMockCookie = typeof getSomethingMockCookie;

export default createMockByCookie<
    MockCookieValue<GetSomethingMockCookie>,
    MyResponseType
>({
    meta: {
        title: "GET /something",
    },
    cookieName: getSomethingMockCookie.name,
    responses: {
        "foo-200": {
            label: "Foo (200)",
            body: { message: "yay" },
        },
        "bar-200": {
            label: "Bar (200)",
            body: { message: "nay" },
        },
        "foobar-500": {
            label: "Foo (500)",
            status: 500,
        },
    },
    defaultResponse: {
        label: "Default (200)",
        body: { message: "default" },
    },
});

More Examples

For more examples see the tests in test/

Inline mocks

Inline mocks let you define mock responses directly in code instead of creating a folder structure.

The URL and HTTP method are declared inside meta rather than being derived from the file path.

Basic inline mock

import apimock from "@forsakringskassan/apimock-express";
import { defineMock } from "@forsakringskassan/apimock-express/helpers";

const mock = defineMock({
    meta: {
        url: "/api/users",
        method: "GET",
    },
    defaultResponse: {
        status: 200,
        body: [
            { userId: 1, name: "Fred Flintstone" },
            { userId: 2, name: "Barney Rubble" },
        ],
    },
});

apimock.config([mock]);

meta.url

Type: String

Required: yes

The URL prefix that this mock responds to. Unlike file-based mocks, the URL must be explicitly set here.

Inline mock URLs support path parameters using colon-prefixed segments. For example, /api/users/:userId matches /api/users/123. Each parameter captures one non-empty path segment and is available as a request parameter when selecting a response. All other URL segments must match exactly.

const mock = defineMock({
    meta: {
        url: "/api/users/:userId",
        method: "GET",
    },
    defaultResponse(request) {
        return {
            status: 200,
            body: { message: `user ${request.parameters.userId} response` },
        };
    },
});

meta.method

Type: String ("GET" | "POST" | "PUT" | "DELETE")

Required: no

The HTTP method to match. When omitted the mock responds to requests of any method.

Mixing inline and file-based mocks

Inline mocks and file-based mocks can be combined

apimock.config([
    { url: "/api/foo", dir: "tests/mock/foo" },
    defineMock({
        meta: { url: "/api/bar", method: "GET" },
        defaultResponse: { body: { bar: true } },
    }),
]);

When a request matches both an inline mock and a file-based mock, the inline mock takes precedence.

Inline mocks with conditional responses

Inline mocks support the same advanced response matching as file-based mocks — matching on request parameters, headers, cookies, or body:

const mock = defineMock({
    meta: {
        url: "/api/users",
        method: "POST",
    },
    responses: [
        {
            request: { body: { name: "" } },
            response: { status: 400, body: { error: "Name is required" } },
        },
    ],
    defaultResponse: {
        status: 201,
        body: { userId: 3, name: "New User" },
    },
});

Browser mode (MSW)

@forsakringskassan/apimock-express has optional support for MSW:

import { setupWorker } from "@forsakringskassan/apimock-express/browser";

await setupWorker("/mock-service-worker.js", [
    {
        meta: {
            url: "/private/foo/basic",
            method: "GET",
        },
        defaultResponse: {
            body: {
                foo: "bar",
            },
        },
    },
]);

The /mock-service-worker.js parameter should be the URL to the msw/mockServiceWorker.js script.

Browser mode (manual)

The matchRequest helper lets you run API mocks entirely in the browser. It accepts an array of mock definitions (created with defineMock) and a native Fetch Request object, and returns a simulated Fetch Response that behaves like a real response.

import { matchRequest } from "@forsakringskassan/apimock-express/browser";
import { defineMock } from "@forsakringskassan/apimock-express/helpers";

// Create basic mock
const mock = defineMock({
    meta: {
        url: "/private/foo/basic",
        method: "GET",
    },
    defaultResponse: {
        body: {
            foo: "bar",
        },
    },
});

const req = new Request("/private/foo/basic", { method: "GET" });
const fetchResponse = await matchRequest([mock], req);

console.log(fetchResponse.status); // => 200
console.log(await fetchResponse.json()); // => {"foo": "bar"}

版本与发布记录

@forsakringskassan/apimock-express 共发布 52 个版本,首次发布于 2024/03/06;过去 12 个月发布了 18 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
4.4.0latest2026/11/069 天前
4.3.02026/10/2323 天前
4.2.12026/09/251 个月前
4.2.02026/09/241 个月前
4.1.02026/09/112 个月前
4.0.02026/09/092 个月前

关于 @forsakringskassan/apimock-express 的常见问题

@forsakringskassan/apimock-express 是什么?

Express middleware for mocking API calls with json & js files during development.

如何安装 @forsakringskassan/apimock-express?

在项目目录运行 npm install @forsakringskassan/apimock-express,或使用 pnpm add / yarn add / bun add。

@forsakringskassan/apimock-express 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@forsakringskassan/apimock-express 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@forsakringskassan/apimock-express 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js ^22 || >= 24。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@forsakringskassan/apimock-express 可以商用吗?

@forsakringskassan/apimock-express 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@forsakringskassan/apimock-express 的下载量有多少?

根据 npm 官方下载统计,@forsakringskassan/apimock-express 在 2026/10/16 – 2026/11/14 这 30 天内被下载 28,667 次,日均约 956 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@forsakringskassan/apimock-express 还在维护吗?

最新版本 4.4.0 发布于 2026/11/06(9 天前);至今共发布 52 个版本,其中过去 12 个月发布了 18 个;首次发布于 2024/03/06。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。