用 TypeScript 写了一个 Mock Protobuf 的 CLI 工具

2022-10-09 10:43:38 +08:00
 jasonkayzk

用 TypeScript 写了一个 Mock Protobuf 的工具

使用

使用 npm 安装:

npm i mock-pb-cli@latest -g

可以使用下面命令查看帮助:

$ mock-pb -h

Usage: mock-protobuf [options] [command]

A tool to mock protobuf

Options:
  -v, --version         output the version number
  -h, --help            display help for command

Commands:
  s|serve [options]     Create a mock server for the given protobuf
  g|generate [options]  Generate mock data for the given protobuf
  help [command]        display help for command

有两个子命令:


Mock JSON 数据

Generate 子命令主要是用来生成 Mock 的 JSON 数据;

例如:

$ mock-pb g

上面的命令会获取当前工作目录下所有的 Proto 文件,并且将 Mock 的数据输出到终端;

例如:

Mocked demo.BasicResponse:
{
    "status": 902735693509892,
    "message": "Vmucue hqxllqx oiloapzwp.",
    "resp": {}
}

Mocked demo.DemoRequest:
{
    "data": "Kqr gxxq."
}

Mocked demo.DemoResponse:
{
    "resp": {
        "status": -6061376970430480,
        "message": "Xpjzjyxrcq eqkmytjo.",
        "resp": {}
    },
    "resp_data": "Ryogd tswayqjsf."
}

默认情况下的 Protobuf 文件搜索路线为 .,你也可以使用 -d 来指定路径!

例如:

$ mock-pb g -d ../test/proto

同时,默认情况下 Mock 数据会打印到终端,你也可以使用 -o 来指定将 Mock 的数据输出到指定的目录!

例如:

$ mock-pb g -o ./mock-pb-output

此时,mock-pb-output 目录下的结果为:

$ tree
.
├── demo
│   ├── BasicResponse.json
│   ├── DemoRequest.json
│   └── DemoResponse.json
├── google.api
│   ├── CustomHttpPattern.json
│   ├── HttpBody.json
│   ├── Http.json
│   └── HttpRule.json
└── google.protobuf
    ├── Any.json
    ├── Api.json
		......
    ├── SourceContext.json
    ├── Type.json
    └── UninterpretedOption.json

输出中的目录结构是根据 Proto 文件中的 package 来产生的!


Mock 服务

基本用法

除了产生 Mock 的数据,也可以直接 Mock 服务接口;

下面的命令会读取当前工作目录下的 Proto 文件,并 Mock 在 Service 中定义了的 Method:

$ mock-pb s

输出如下:

Handling routePath: /Demo
Handling routePath: /demo/DemoServiceAnotherDemo
restify listening at http://[::]:3333

在服务端启动时,会打印出每个接口的请求路径;

默认情况下的服务端口号为:3333,你可以使用 -p 来自定义端口;

例如:

  • mock-pb s -p 13333

如果你在你的 Method 中通过 google.api.http 定义了请求路径,那么在 Mock 服务的时候会使用这个路径;

例如:

service DemoService {
  rpc Demo(DemoRequest) returns (DemoResponse) {
    option (google.api.http) = {
      post: "/Demo"
      body: "*"
    };
  }
}

如果没有指定请求路径,那么请求路径为:/{ProtobufPackageName}/{ProtobufMethodName}

例如:

syntax = "proto3";

package demo;

service DemoService {
  rpc AnotherDemo(AnotherDemoRequest) returns (AnotherDemoResponse) {}
}

当服务启动后的请求路径为:

$ curl localhost:3333/demo/DemoServiceAnotherDemo
{"resp":{"status":-843357854531144,"message":"Vzby.","resp":{}},"resp_data":"Kvia gfkcggmuo."}

自定义返回值

有时候你可能并不想 Mock 一些像下面这些无意义的数据:

{"resp":{"status":-843357854531144,"message":"Vzby.","resp":{}},"resp_data":"Kvia gfkcggmuo."}

而是想要自定义一些有用的返回值,比如:

{"resp":{"status":200,"message":"ok"},"resp_data":{"Message":"This is a demo message"}}

此时可以创建配置文件,例如:

mock-protobuf.config.json

{
    "ResponseValue": [
        {
            "MethodName": "demo.Demo",
            "Data": {
                "Hello": "world"
            }
        },
        {
            "MethodName": "demo.AnotherDemo",
            "Data": {
                "resp": {
                    "status": 200,
                    "message": "ok"
                },
                "resp_data": {
                    "Message": "This is a demo message"
                }
            }
        }
    ]
}

其中 MethodName 是 Proto 文件中 Method 的全名:package.method

同时,你也可以通过 -c 请求来指定你的配置文件路径,例如: -c ./mock-protobuf.config.json

下面是一个完整的命令行例子:

$ npm run dev -- s -i demo -c ./mock-protobuf.config-demo.json

使用自定义返回值后的响应如下:

$ curl localhost:3333/Demo
{"Hello":"world"}

$ curl localhost:3333/demo/DemoServiceAnotherDemo
{"resp":{"status":200,"message":"ok"},"resp_data":{"Message":"This is a demo message"}}

过滤条件

有的时候我们并不想 Mock 所有的 Proto 定义,此时可以使用 Filter 过滤条件;

有两种方式进行过滤:

上面的 <string> 被定义为一个 JS 中的正则表达式 RegExp,所以可以使用类似于正则表达式的方式对 Proto 定义进行匹配:packageName.serviceName.methodName

多个条件使用 , 分隔!


Include 过滤条件

当使用 Include 过滤条件,只有匹配的 Proto 定义才会被 Mock ;

例如:

$ mock-pb g -i demo

Mocked demo.BasicResponse:
{
    "status": -978663427598816,
    "message": "Iymo zomttydmb.",
    "resp": {}
}

Mocked demo.DemoRequest:
{
    "data": "Mdnbfxbvoq khrbwyu sxmkev jss."
}

Mocked demo.DemoResponse:
{
    "resp": {
        "status": 6207610394471496,
        "message": "Dkwse mmhmuhhunb.",
        "resp": {}
    },
    "resp_data": "Fqwkd noiefpr ntjbcfydl."
}

Mocked demo.AnotherDemoRequest:
{
    "name": "Puvujqy kyxl hshuysly.",
    "age": 175838119803604
}

Mocked demo.AnotherDemoResponse:
{
    "resp": {
        "status": -7659482750118844,
        "message": "Fygec kyzysqqga svimupy nbfrjt.",
        "resp": {}
    },
    "resp_data": "Mpgjtjsbr qfspgkb xmpji."
}

上面的命令只会为 demo.* 产生 Mock 数据(即:package 为 demo 的那些定义)!

另外一个例子:

$ mock-pb g -i demo.DemoRequest.*

Mocked demo.DemoRequest:
{
    "data": "Ewqzspj hjkfvvc froqdhkwe fkqsdg dytidwli."
}

此时只会 Mock:demo.DemoRequest 这一个 Message !


Exclude 过滤条件

相反的,-e 产生将会排除那些匹配的 Message ;

例如:

$ mock-pb g -e demo.*,google.protobuf.* -o mock-pb-gen

$ tree
.
└── google.api
    ├── CustomHttpPattern.json
    ├── HttpBody.json
    ├── Http.json
    └── HttpRule.json

上面的命令将不会 Mock demo.*google.protobuf.* 下的 Message !

<font color="#f00">注意:当你同时使用 include and exclude 两个过滤器,exclude 会永远首先生效!</font>

例如:

$ mock-pb g -i demo -e demo

什么都不会输出,因为所有的内容都被过滤掉了!


关于整个开发的过程以及思路,我也放到了我的博客:

希望对 TypeScript 初学者,以及想使用 TypeScript 编写 CLI 小工具的小伙伴们有帮助!❤️

1500 次点击
所在节点    分享创造
0 条回复

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/885456

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX