gRPC Mock Server
PowerMock是一个Mock Server的实现,它同时支持HTTP与gRPC协议接口的Mock,并提供了灵活的插件功能。
这个工具面向于前后端、测试等对有接口Mock需求的开发人员,也可以作为一个通用的Mock服务,部署在网关架构或API管理平台中,实现降级、接口Mock等功能。
- PowerMock
- 功能
- 示例
- 一、较为高级的用法
- 1. 条件场景一
- 2. 条件场景二
- 二、从Hello World开始吧
- 1. 先Mock一个HTTP接口
- 2. 再mock一个gRPC接口
- 一、较为高级的用法
- 安装
- 通过Go安装
- 开箱即用版本
- 通过Makefile编译
项目地址
项目地址:PowerMock
功能
作为一个Mock Server,PowerMock具有以下的核心功能:
- 支持 HTTP协议 与 gRPC协议 接口的Mock。
- 支持配置 Javascript 等脚本语言来动态生成响应。
- 支持对一个接口配置多种响应,并按照条件进行区分。
- 匹配条件支持多种运算符(AND/OR/>/</=等)。
- 支持返回静态数据以及 特定领域的随机数据。
- 支持 插件 功能,可以通过编写插件实现其他匹配或Mock引擎。
- 同时提供HTTP与gRPC接口,可以动态对MockAPI进行 增删改查 。
- 开箱即用的Redis存储,并支持自由拓展其他存储引擎,比如MySQL、etcd。
- 同时支持 windows / darwin / linux 的 32 位 与 64 位。
- 语言无关,任何使用HTTP协议或gRPC协议的项目均可以使用本工具。
示例
一、较为高级的用法
本示例可以在 示例代码 找到对应资料
本示例必须使用v8版本的powermock,才能完整支持Javascript的功能
以下面这份配置为示例:
uniqueKey: "advanced_example"
path: "/examples.greeter.api.Greeter/Hello"
method: "POST"
cases:- condition:simple:items:- operandX: "$request.header.uid"operator: "<="operandY: "1000"response:simple:header:x-unit-id: "3"x-unit-region: "sh"trailer:x-api-version: "1.3.2"body: |{"timestamp": "1111", "message": "This message will only be returned when uid <= 1000", "amount": "{{ $mock.price }}"}- condition:simple:items:- operandX: "$request.header.uid"operator: ">"operandY: "1000"response:script:lang: "javascript"content: |(function(){function random(min, max){return parseInt(Math.random()*(max-min+1)+min,10);}return {code: 0,header: {"x-unit-id": (request.header["uid"] % 5).toString(),"x-unit-region": "bj",},trailer: {"x-api-version": "1.3.2",},body: {timestamp: Math.ceil(new Date().getTime() / 1000),message: "this message is generated by javascript, your uid is: " + request.header["uid"],amount: random(0, 5000),},}})()
这份配置定义了一个MockAPI
,用于匹配所有路径为 /examples.greeter.api.Greeter/Hello
,方法为 POST
的请求,它包含了两个场景,能够实现这样的效果:
1. 条件场景一
当请求 Header 中的 uid <= 1000
时:
- Response Header 中写入:
x-unit-id: "3"
x-unit-region: "sh"
- Response Trailer 中写入:
x-api-version: "1.3.2"
- Response Body 中写入:
{"timestamp": "1111", "message": "This message will only be returned when uid <= 1000", "amount": "{{ $mock.price }}"}
其中的 {{ $mock.price }}
是魔法变量,用于返回一个随机的价格数据。最终,客户端收到的 Response Body
类似于:
{"timestamp": "1111","message": "This message will only be returned when uid <= 1000","amount": 7308.4
}
2. 条件场景二
当请求 Header 中的 uid > 1000
时,通过执行以下Javascript脚本返回响应:
(function(){function random(min, max){return parseInt(Math.random()*(max-min+1)+min,10);}return {code: 0,header: {"x-unit-id": (request.header["uid"] % 5).toString(),"x-unit-region": "bj",},trailer: {"x-api-version": "1.3.2",},body: {timestamp: Math.ceil(new Date().getTime() / 1000),message: "this message is generated by javascript, your uid is: " + request.header["uid"],amount: random(0, 5000),},}
})()
在这个脚本中,根据请求的 Header,以及一些内置或自定义函数来生成了响应的code、header、trailer与body。
最终客户端收到的响应体类似于:
{"timestamp": 1622093545,"message": "this message is generated by javascript, your uid is: 2233","amount": 314
}
它描述了一个相对复杂的场景,当然可能你的需求比较简单,实战的话,我们先从Hello World开始吧!
二、从Hello World开始吧
本示例可以在 示例代码 找到对应资料
首先,创建一个配置文件:
log:pretty: truelevel: debug
grpcmockserver:enable: trueaddress: 0.0.0.0:30002protomanager:protoimportpaths: [ ]protodir: ./apis
httpmockserver:enable: trueaddress: 0.0.0.0:30003
apimanager:grpcaddress: 0.0.0.0:30000httpaddress: 0.0.0.0:30001
pluginregistry: { }
plugin:simple: { }grpc: { }http: { }script: { }redis:enable: falseaddr: 127.0.0.1:6379password: ""db: 0prefix: /powermock/
将编译好的PowerMock与上面创建好的配置文件放到同一个目录中,像下面这样:
➜ ls -alh
total 45M
drwxrwxrwx 1 storyicon storyicon 4.0K May 27 14:18 .
drwxrwxrwx 1 storyicon storyicon 4.0K May 24 11:43 ..
-rwxrwxrwx 1 storyicon storyicon 546 May 27 14:16 config.yaml
-rwxrwxrwx 1 storyicon storyicon 45M May 27 14:18 powermock
然后执行
➜ ./powermock serve --config.file config.yaml
如果没有端口冲突的话,你应该已经可以看到服务运行起来了!
1. 先Mock一个HTTP接口
在上面的目录下,创建一个名为 apis.yaml 的文件:
uniqueKey: "hello_example_http"
path: "/hello"
method: "GET"
cases:- response:simple:header:x-unit-id: "3"x-unit-region: "sh"trailer:x-api-version: "1.3.2"body: |hello world!
然后运行:
➜ ./powermock load --address=127.0.0.1:30000 apis.yaml
2:32PM INF start to load file component=main file=load.go:59
2:32PM INF mock apis loaded from file component=main count=1 file=load.go:64
2:32PM INF start to save api component=main file=load.go:76 host= method=GET path=/hello uniqueKey=hello
2:32PM INF succeed! component=main file=load.go:89
这样,我们描述的MockAPI就创建起来了。
通过 curl
或者你的浏览器请求 http://127.0.0.1:30003/hello
,可以看到返回给我们 hello world 了!
➜ curl http://127.0.0.1:30003/hello -i
HTTP/1.1 200 OK
Content-Type: application/json
X-Unit-Id: 3
X-Unit-Region: sh
Date: Thu, 27 May 2021 06:36:28 GMT
Content-Length: 12hello world!
2. 再mock一个gRPC接口
在上面的目录中,创建一个 apis 目录,使整个目录结构像下面这样:
➜ ls -alh
total 45M
drwxrwxrwx 1 storyicon storyicon 4.0K May 27 14:42 .
drwxrwxrwx 1 storyicon storyicon 4.0K May 27 14:37 ..
drwxrwxrwx 1 storyicon storyicon 4.0K May 27 14:23 apis
-rwxrwxrwx 1 storyicon storyicon 1.8K May 27 14:32 apis.yaml
-rwxrwxrwx 1 storyicon storyicon 546 May 27 14:16 config.yaml
-rwxrwxrwx 1 storyicon storyicon 45M May 27 14:18 powermock
在 apis 目录中创建我们的 greeter.proto:
syntax = "proto3";package examples.greeter.api;
option go_package = "github.com/bilibili-base/powermock/examples/helloWorld/apis;apis";service Greeter {rpc Hello(HelloRequest) returns (HelloResponse);
}message HelloRequest {string message = 2;
}message HelloResponse {string message = 2;
}
现在整个目录结构像这样:
.
├── apis
│ └── greeter.proto
├── apis.yaml
├── config.yaml
└── powermock
重新运行我们的 powermock
来加载我们新写的proto文件:
➜ ./powermock serve --config.file config.yaml
2:55PM INF starting load proto from: ./apis component=main.gRPCMockServer.protoManager file=service.go:102
2:55PM INF api loaded component=main.gRPCMockServer.protoManager file=service.go:131 name=/examples.greeter.api.Greeter/Hello
在启动日志中可以看到我们新创建的 proto 文件已经被加载到 PowerMock 中了。
将我们的 apis.yaml 文件修改成下面的内容:
uniqueKey: "hello_example_http"
path: "/hello"
method: "GET"
cases:- response:simple:header:x-unit-id: "3"x-unit-region: "sh"trailer:x-api-version: "1.3.2"body: |hello world!---uniqueKey: "hello_example_gRPC"
path: "/examples.greeter.api.Greeter/Hello"
method: "POST"
cases:- response:simple:header:x-unit-id: "3"x-unit-region: "sh"trailer:x-api-version: "1.3.2"body: |{"message": "hello world!"}
可以看到,里面添加了一个名为 “hello_example_gRPC” 的 MockAPI,我们通过下面的命令装载它:
➜ powermock load --address=127.0.0.1:30000 apis.yaml
3:06PM INF start to load file component=main file=load.go:59
3:06PM INF mock apis loaded from file component=main count=2 file=load.go:64
3:06PM INF start to save api component=main file=load.go:76 host= method=GET path=/hello uniqueKey=hello_example_http
3:06PM INF start to save api component=main file=load.go:76 host= method=POST path=/examples.greeter.api.Greeter/Hello uniqueKey=hello_example_gRPC
3:06PM INF succeed! component=main file=load.go:89
这样,我们的MockAPI就被添加到PowerMock中了。
如果你的环境中有BloomRPC之类的工具的话,可以先通过BloomRPC加载 greeter.proto,然后调用 127.0.0.1:30002
:
可以看到,调用成功返回了 “hello world”。
如果使用编程语言进行调用的话,以 golang 为例,通过下面的代码调用 PowerMock
:
func main() {fmt.Println("starting call mock server")conn, err := grpc.Dial("127.0.0.1:30002", grpc.WithInsecure())if err != nil {panic(err)}client := apis.NewGreeterClient(conn)var header, trailer metadata.MDstartTime := time.Now()resp, err := client.Hello(context.TODO(), &apis.HelloRequest{Message: "hi",}, grpc.Header(&header), grpc.Trailer(&trailer))if err != nil {panic(err)}fmt.Printf("[elapsed] %d ms \r\n", time.Since(startTime).Milliseconds())fmt.Printf("[headers] %+v \r\n", header)fmt.Printf("[trailer] %+v \r\n", trailer)fmt.Printf("[response] %+v \r\n", resp.String())
}
日志输出是这样的:
starting call mock server
[elapsed] 2 ms
[headers] map[content-type:[application/grpc] x-unit-id:[3] x-unit-region:[sh]]
[trailer] map[x-api-version:[1.3.2]]
[response] message:"This message will only be returned when uid <= 1000"
可以看到,我们的接口被成功Mock出来了!
安装
通过Go安装
安装普通版本,无Javascript支持:
go install github.com/bilibili-base/powermock/cmd/powermock
安装V8版本,支持Javascript:
go install github.com/bilibili-base/powermock/cmd/powermock-v8
开箱即用版本
如果你没有定制插件的需求,开箱即用版本 非常适合你。
通过Makefile编译
如果你是 linux/darwin/wsl
的用户,推荐使用 makefile 来进行安装:
➜ git clone https://github.com/bilibili-base/powermock
➜ cd powermock
➜ make build_linux_v8
➜ make build_linux
➜ make build_darwin
➜ make build_windows
当然也可以直接进行编译:
➜ cd ./cmd/powermock
➜ go install
➜ go build .
gRPC Mock Server相关推荐
- 1分钟搭建极简mock server
摘自博客园:https://www.cnblogs.com/mikasama/p/9838480.html 1.无聊的背景.起源: 如今的业务系统越来越复杂庞大,各个功能直接的调用也是多如牛毛,但如果 ...
- 如何优雅的使用Mock Server
事出有因 昨天跟同事讨论我们在用的rap2(一个集接口编写和mock server的开源项目)和刚上线了一个easy-mock的server,到底哪个好用. 我们主要讨论的点有个两个: 接口的一致性. ...
- python接口测试实战_Python接口测试实战5(下) - RESTful、Web Service及Mock Server
课程目录 更多学习资料请加添加作者微信:superz-han获取 本节内容 REST及RESTful API Web Service XML解析 Mock Server REST及RESTful AP ...
- java mockserver搭建_搭建Mock Server
1.为什么要搭建mock-server? 为了更好的分工合作,让前端能在不依赖后端环境的情况下进行开发,其中一种手段就是为前端开发者提供一个 web 容器,这个本地环境就是 mock-server. ...
- SAP UI5 应用开发教程之六十三 - 基于 OData V4 的本地 Mock Server 实现的深入介绍试读版
一套适合 SAP UI5 初学者循序渐进的学习教程 教程目录 SAP UI5 本地开发环境的搭建 SAP UI5 应用开发教程之一:Hello World SAP UI5 应用开发教程之二:SAP U ...
- SAP UI5 应用开发教程之六十三 - 基于 OData V4 的本地 Mock Server 实现的深入介绍
学习本步骤之前,请确保你已经复习了步骤 26 和 步骤 62 的知识: SAP UI5 应用开发教程之二十六 - OData 服务配合 Mock 服务器的使用步骤详解 SAP UI5 应用开发教程之六 ...
- 如何以 mock server 的方式本地启动 SAP UI5 应用,使它不连接服务器端 OData 服务
我们在做 SAP UI5 开发时,在视图逻辑没有开发完毕时,往往不希望连接服务器端的 OData 服务进行联调,而仅仅连接本地端的测试数据. 本文介绍如果启动本地 mock server,将 SAP ...
- 搭建Mock Server
搭建Mock Server 1.为什么要搭建mock-server? 为了更好的分工合作,让前端能在不依赖后端环境的情况下进行开发,其中一种手段就是为前端开发者提供一个 web 容器,这个本地环境就是 ...
- pythonflaskmock数据_Flask实现简单Mock Server
Mock Server充当的角色: Mock server在实际项目中的意义就相当于数据库.将我想要的数据返回给我就行,我并不关心你怎么逻辑处理的. 一般的应用程序请求方式是GET和POST. Fla ...
- 基于django rest framework的mock server实践
网上找了一下mock server的实现,发现python的基本都是基于flask来实现的,因最近在学django,就尝试用drf实现了下: A brief introduction of sui_m ...
最新文章
- 深度神经网络混合精度训练
- 暑期集训1:C++STL 练习题C:HDU-1263
- 【每日scrum】NO.5
- Tomcat7.0+的JNDI问题
- cesium 设置地球默认区域为中国 一键返回默认区域
- [Unity] GameFramework 学习记录 3
- android 中 DOM解析xml
- 超简单!基于Python搭建个人“云盘”
- 转:Loadrunner打开https报错“Internet…
- 树莓派运行java_【树莓派】用树莓派4可以流畅运行java版minecraft?
- D3D自定义的设备丢失对象
- Mysql SQLyog 使用详解
- 互联网30年,泡沫如梦,一个个泡沫和风口过后,会是什么样的结局
- Linux 常用系统故障(修复MBR扇区故障、修复GRUB引导故障、遗忘root用户密码、修复文件系统、磁盘配额等)
- 1.国民技术N32G45X例程之-串口打印
- 一款懒人必备的Python爬虫神器
- hdu5804(BestCoder Round #86 A)
- 传感器为什么在低量程偏差大_高精度、超低量程的压力传感器概述
- GF(2^8)的加法与乘法计算
- Wilcoxon rank-sum 和 signed-rank
热门文章
- C语言大作业--小型工资管理系统
- 神策分析 iOS SDK 代码埋点解析 | 数据采集
- mysql 中国省份城市数据库表
- Android实现连线题效果
- python保存到txt_python保存成文本文件
- 开源阅读书源_免费开源网络文学阅读器(万本小说免费阅读)
- a59s刷机包卡刷 oppo_OPPO A59s 5.1 ROM刷机包 ColorOS 精简卡刷包 ROOT权限
- USB接口IC读写器oem软件_AB密码完整解决方案/读写卡测试程序及源代码/c++builder源代码(2)
- ICD3 - Cannot connect to USB device. Unrecognized endpoint.
- 固态硬盘用软件测试掉速严重,SSD固态硬盘掉速怎么办?手动执行TRIM指令缓解固态硬盘掉速方法...