@forsakringskassan/ apimock- 表达
一个用于 grunt-contrib-连接插件的中间软件,该插件用文件系统中的json-文件来嘲弄一个 REST api. 使您的客户端代码很容易独立于服务器进行开发和测试.
这原本是从 连接- 相扑 通过快车叉 apimock 表达式。 。 。 .
与原文的主要区别:
- 与快通和通通同时工作(不特别要求Grunt).
- 支持两者
.mjs/.cjs/.js/.ts/.mts财务报告和审定财务报表.json嘲讽. - 支持通配符作为最终路径组件.
- 改进和可配置的伐木.
- 帮助者,例如:
defineMock帮助 IDE 写作模拟. - 字体支持 .
- 已建 Vite 插件 .
使用量
npm 安装 - save- dev @ forsakringskassan/ apimock- expression
连接
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);
有快车
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);
与维特
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 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);
},
},
});
模拟文件和目录结构
被嘲笑的API包括一些 .mjs/.cjs/.js/.ts/.mts 或者说 .json 在代表 API 的目录结构中的文件.
例如,采用这种配置 { "url": "/myApp/api/", "dir": "mymockdirectory" },然后阿皮莫克这样工作:
| 方法 | 请求 | 文件名 |
|---|---|---|
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 |
文件的格式可以简单或者高级格式.
- 在使用简单格式时,文件内容会被作为回复正文和http-status 200被返回.
- 在使用高级格式时,可以根据请求参数,正文参数,请求头或请求的cookie来指定不同的响应和不同的http-status.
目录
如果模拟器是一个目录,它可以包含 __${method}.{js,json} 例如,如果配置如下:
{
"url": "/myApp/api/foo",
"dir": "mymockdirectory/foo"
}
何时 mymockdirectory/foo 请求是这样的目录 :
| 方法 | 请求 | 文件名 |
|---|---|---|
GET | /myApp/api/foo | mymockdirectory/foo/__get.json |
POST | /myApp/api/foo | mymockdirectory/foo/__post.json |
当模拟下的 API 没有前缀, 而我们不想应用时, 这大多是有用的 / 作为模拟url.
通关卡/ 全局文件
如果文件的格式 __default.json 存在于文件夹中,如果找不到特定文件,则会使用.
模拟配置
apimock.config
类型 : object 或者说 array 对象
含有 apimock 配置的对象. 见下文. 如果您想要模拟不同的 URL:s 来区分目录, 也可以成为一系列对象 .
apimock.config([
{ url: "/api1/", dir: "test/api1" },
{ url: "/api2/", dir: "test/api2", delay: 500 },
]);
url
类型 : String
要求 : 对
您想要嘲笑的 REST - api 的url 开始 .
dir
类型 : String
要求 : 对
Apimock 模拟文件所在的目录 . 位置相对于当前工作目录.
delay
类型 : Number
要求 : 没有
默认值 : 0 个
基数延迟(以毫秒为单位),用于此url的所有请求,在模拟器回复之前.
文件格式
模拟文件可以简单或高级的形式写成JSON或JS.
如果可以获取相同的响应正文和HTTP- status 200, 请使用简单格式 .
如果您需要根据请求参数获得不同的响应或HTTP-状态,请求正文,请求头或cookie使用高级格式.
简单格式
这很简单. 文件内容将作为HTTP-status 200的回复正文返回.
mymockdirectory/users.json数字 :
[
{ "userId": 1, "name": "Fred Flintstone" },
{ "userId": 2, "name": "Barney Rubble" }
]
高级格式
如果文件中的对象有变量, apimock 将会切换到高级格式 responses 或/和变量 defaultResponse 根位为!=未定义.
如果没有一个变量被定义,那么内容就被认为是简单的格式.
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" }
]
}
}
默认响应
类型 : Object
要求 : 对
如果响应数组中没有任何请求匹配, 默认响应将被重现 .
默认响应. status
类型 : Number
要求 : 没有
默认值 : 200个
HTTP 状态 .
默认响应. body
类型 : Object
要求 : 对
反应体.
默认Response.delay
类型 : Number
要求 : 没有
默认值 : 0 个
模拟器出现前的延迟数以毫秒计将做出回应.
答复
类型 : Array
要求 : 没有
包含所需请求和将返回的响应的一系列对象.
答复
类型 : Object
要求 : 对
描述匹配标准.
答复、请求、参数
类型 : Object
要求 : 没有
请求中需要匹配的参数名称和值 .
回应 请求 机构
类型 : Object
要求 : 没有
此响应需要匹配的请求对象参数的名称和值 .
答复、要求、标题
类型 : Object
要求 : 没有
此响应需要匹配的请求头名称和值 .
回应
类型 : Object
要求 : 没有
此响应需要匹配的请求 cookie 的名称和值 .
答复
类型 : Object
要求 : 对
描述如果请求匹配将重现的响应 .
答复、答复、状况
类型 : Number
要求 : 没有
默认值 : 200个
HTTP 状态 .
答 答 问 问 题
类型 : Object
要求 : 对
反应体.
答复、答复、延迟
类型 : Number
要求 : 没有
默认值 : 0 个
模拟器出现前的延迟数以毫秒计将做出回应.
实例
取决于请求参数的不同响应:
{
"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"
}
}
}
取决于请求机构的不同答复:
{
"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"
}
}
}
请求参数和请求正文的组合
{
"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"
}
}
}
不同请求标题的不同响应 :
{
"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"
}
}
}
根据请求 cookie 的不同响应 :
{
"responses": [
{
"request": {
"cookies": {
"foo": "foo"
}
},
"response": {
"status": 400,
"body": {
"message": "When cookie foo=foo"
}
}
}
],
"defaultResponse": {
"status": 201,
"body": {
"message": "Nothing matches. Default 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
}
}
使用帮助
使用提供的帮助函数设置模拟往往比较简单.
这个 createMockByCookie(...) 帮助函数
这个 createMockByCookie(...) 帮助函数根据特定的cookie设置模拟响应.
如果使用正确,Typescript还可以帮助为饼干及其可能值提供类型安全.
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" },
},
});
更多实例
更多实例见测试/测试中的测试
内在模拟
Inline 模拟让您直接在代码中定义模拟响应,而不是创建文件夹结构.
URL 和 HTTP 方法在内部声明 meta 而不是从文件路径导出.
基本内含模拟
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
类型 : String
要求 : 对
此模拟应答的 URL 前缀 。 与基于文件的模拟不同,URL必须在这里明确设置.
内置模拟 URL 支持使用冒号前缀的路径参数. 对于
实例, /api/users/:userId 匹配 /api/users/123。每个参数捕获
一个非空路段, 当
选择一个响应。 所有其他 URL 片段必须精确匹配 .
const mock = defineMock({
meta: {
url: "/api/users/:userId",
method: "GET",
},
defaultResponse(request) {
return {
status: 200,
body: { message: `user ${request.parameters.userId} response` },
};
},
});
meta.method
类型 : String (单位:千美元)"GET" | "POST" | "PUT" | "DELETE"(中文(简体) )
要求 : 没有
HTTP方法可以匹配. 省去模型时,会响应任何方法的要求.
混合内线和基于文件的模拟
内置模拟和基于文件的模拟可以合并
apimock.config([
{ url: "/api/foo", dir: "tests/mock/foo" },
defineMock({
meta: { url: "/api/bar", method: "GET" },
defaultResponse: { body: { bar: true } },
}),
]);
当一个请求既匹配了内在模拟,又匹配了基于文件的模拟,则内在模拟优先.
内含有条件的反应
Inline 模拟支持与基于文件的模拟相同的高级响应匹配——在请求参数,标题,饼干或正文上匹配:
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" },
},
});
浏览器模式 (MSW)
@forsakringskassan/apimock-express 有可选支持 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",
},
},
},
]);
这个 /mock-service-worker.js 参数应该是 msw/mockServiceWorker.js 剧本.
浏览器模式( 手工)
匹配请求帮助器让您运行 API 完全在浏览器中模拟 .
它接受一系列模拟定义( 用定义Mock 创建) 和本地获取 Request 对象,并返回模拟的获取 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"}