MockServer
基于Flask实现的一个简易Mock平台,使用标准json结构体编写Mock Api https://github.com/yinquanwang/MockServer
Key Features
- 遵循Http协议,支持
GET、POST、PUT、DELETE常用http请求方式 - mock结构体为标准json结构,支持参数内容规则制定以及对象返回信息
- 内置常用校验器,equals、contains、between、length、type, 可灵活自己扩展
- 支持自定义报文Valid与Invalid,返回报文可以是任意类型
- 数据类型丰富,支持string、int、float、list、dict
得益于Flask强大的路由系统,设计核心就是将所有请求的path归一化到一个视图函数处理:
@app.route('/<path:path>', methods=['GET', 'PUT', 'DELETE', 'POST'])
def dispatch_request(path):
"""
mock view logic
:param path: request url for mock server
:return: response msg that use default or custom defined
"""
m = models.Api.query.filter_by(url=request.path, method=request.method).first_or_404()
body = json.loads(m.body)
return domain_server(**body)
@app.errorhandler(404)
def url_not_found(error):
return json.dumps({
"status": 404,
"msg": "the request url not found,please check"
})
如果mock脚本不自定义返回报文,由系统默认提供,默认标准json结构体
VALID = {
"success": True,
"code": "0000",
"msg": "success"
}
INVALID = {
'code': '0020',
'msg': 'request data invalid',
'success': False
}
MISS = {
'code': '0021',
'msg': 'request data missed',
'success': False
}
TYPE_NOT_MATCH = {
"success": False,
"code": "0001",
}
EQUALS = {
"success": False,
"code": "0005",
}
NOT_BETWEEN = {
"success": False,
"code": "0007",
}
STR_NOT_CONTAINS = {
"success": False,
"code": "0004",
}
STR_TOO_LONG = {
"success": False,
"code": "0006",
}
由此我们必须实现一个校验器,对各个字段进行一些基本校验
class Validator:
"""
Validator for mock check
"""
@classmethod
def valid(cls, response=None):
return get_response(response, VALID)
@classmethod
def type_not_match(cls, type, data, response=None):
msg = '{data} must be {type} type'.format(data=data, type=type)
TYPE_NOT_MATCH['msg'] = msg
if type == 'int':
if not isinstance(data, int):
return get_response(response, TYPE_NOT_MATCH)
elif type == 'float':
if not isinstance(data, float):
return get_response(response, TYPE_NOT_MATCH)
elif type == 'string':
if not isinstance(data, str):
return get_response(response, TYPE_NOT_MATCH)
elif type == 'bool':
if not isinstance(data, bool):
return get_response(response, TYPE_NOT_MATCH)
elif type == 'list':
if not isinstance(data, list):
return get_response(response, TYPE_NOT_MATCH)
elif type == 'dict':
if not isinstance(data, dict):
return get_response(response, TYPE_NOT_MATCH)
else:
return False
@classmethod
def is_not_equals(cls, data, expect, response=None):
if data != expect:
msg = '{data} must be equals {expect}'.format(data=data, expect=expect)
EQUALS['msg'] = msg
return get_response(response, EQUALS)
else:
return False
@classmethod
def is_not_between(cls, data, between, response=None):
try:
min = between[0]
max = between[1]
except IndexError:
return {'msg': 'mock config error'}
if data > max or min < min:
msg = '{data} must be between in {between}'.format(data=data, between=between)
NOT_BETWEEN['msg'] = msg
return get_response(response, NOT_BETWEEN)
else:
return False
@classmethod
def is_not_contains(cls, data, expect, response=None):
if data not in expect:
msg = '{data} not in {expect}'.format(data=data, expect=expect)
STR_NOT_CONTAINS['msg'] = msg
return get_response(response, STR_NOT_CONTAINS)
else:
return False
@classmethod
def is_too_long(cls, data, length, response=None):
if len(data) > length:
msg = '{data} is too long, max length is {length}'.format(data=data, length=length)
STR_TOO_LONG['msg'] = msg
return get_response(response, STR_TOO_LONG)
else:
return False
接下来便是对请求数据与期望数据匹配,从而返回相应报文了
def domain_server(**kwargs):
"""
used for POST PUT DELETE
:param kwargs: standard json mock scripts
:return: response msg
"""
data = kwargs.get('data', {})
invalid = kwargs.get('invalid', {})
if request.json:
form = request.json
elif request.form:
form = request.form
elif request.args:
form = request.args
if data is {}: # do not have any parameters
return Validator.valid(response=kwargs.get('valid'))
else:
if len(form) != len(data): # data do not matched
return json.dumps(MISS, ensure_ascii=False)
for key in form.keys():
if key not in data.keys():
return json.dumps(INVALID, ensure_ascii=False)
for key, value in form.items(): # usually validators
expect = data.get(key)
type = expect.get('type')
msg = Validator.type_not_match(type, value, response=invalid.get('type'))
if msg:
return msg
contains = expect.get('contains')
if contains:
msg = Validator.is_not_contains(value, contains, response=invalid.get('contains'))
if msg:
return msg
equals = expect.get('equals')
if equals:
msg = Validator.is_not_equals(value, equals, response=invalid.get('equals'))
if msg:
return msg
long = expect.get('long')
if long:
msg = Validator.is_too_long(value, long, response=invalid.get('length'))
if msg:
return msg
between = expect.get('between')
if between:
msg = Validator.is_not_between(value, between, response=invalid.get('between'))
if msg:
return msg
return Validator.valid(response=kwargs.get('valid'))
指导说明
- example for get request
json { "data": { "password": { "equals": "lcc", "type": "string" }, "username": { "equals": "lcc", "type": "string" } }, "invalid": { "equals": { "msg": "恭喜啊,查询到该账号了" }, "type": "类型不匹配啊" }, "method": "GET", "name": "查询接口", "url": "/get/", "valid": { "msg": "查询成功啦", "success": true } }例如上述json结构体,此get请求有两个参数username,password, type=string,equals=lcc ,规定了valid报文和invalid中的equals报文
- example for post 支持json和form,系统会自动进行分辨
json { "data": { "email": { "equals": { "lcc": "lcc@qq.com", "yqw": "yqw@qq.com" }, "type": "dict" }, "password": { "type": "string" }, "username": { "equals": "lcc", "length": 10, "type": "string" } }, "invalid": { "equals": { "msg": "哥们,类型不匹配啊" }, "type": "类型不匹配啊" }, "method": "POST", "name": "注册接口", "url": "/register/", "valid": { "msg": "注册成功啦" } } - example for put
json { "data": { "identity": { "equals": "1", "type": "string" } }, "invalid": { "equals": { "msg": "啊哦 该账号没有记录哦" }, "type": "类型不匹配啊" }, "method": "put", "name": "更新接口", "url": "/put/", "valid": { "msg": "查询成功啦", "success": true } } - example for delete
json { "data": { "account": { "equals": "lcc123456", "length": 10, "type": "string" } }, "invalid": { "equals": { "msg": "啊哦 该账号没有记录哦" }, "type": "类型不匹配啊" }, "method": "delete", "name": "删除接口", "url": "/del/1/", "valid": { "msg": "删除成功啦", "success": true } }## 由于第一次接触Flask,mock的理解自己可能也有偏差,所以还请各位大神不要见怪
本地开发环境部署
- git clone 或者 checkout至本地目录
- 修改:MockServer/config.py 数据库相关配置
python USERNAME = 'root' PASSWORD = 'lcc123456' HOST = '127.0.0.1' DB = 'MockServer' - 安装相应依赖库
bash pip install -r requirements.txt - 创建MockServer数据库, 默认DB是MockServer
- 生成数据库迁移脚本,应用表结构
bash python manage.py db init python manage.py db migrate python manage.py db upgrade - Start Server
bash python run.py
MockServer的更多相关文章
- mockServer学习
mockServer学习 很喜欢mockserver官方主页的背景颜色和格式 官方主页如下: http://www.mock-server.com/
- 【Mock】【接口测试】【面试】mock-server 环境搭建—加分项!
mock-server 环境搭建 前言 mock 除了用在单元测试过程中,还有一个用途,当前端开发在开发页面的需要服务端提供 API 接口 此时服务端没开发完成,或者说没搭建测试环境,这个时候前端开发 ...
- 【Mock】mock-server 环境搭建
前言 mock 除了用在单元测试过程中,还有一个用途,当前端开发在开发页面的时候,需要服务端提供 API 接口 此时服务端没开发完成,或者说没搭建测试环境,这个时候前端开发会自己 mock一个 api ...
- 使用mockserver来进行http接口mock
转载自:https://blog.csdn.net/heymysweetheart/article/details/52227379:(注,这个不是很符合我的要求,它主要的作用是可以通过简单的代码就能 ...
- nodejs结合apiblue实现MockServer
apiblue功能很强大,里面支持很多插件,这些插件能够为restfulAPI提供接口文档自动生成,甚至Mockserver的功能,当然,好多插件还是有很多坑的.下面用apiblue实现下面的业务需求 ...
- MockServer 入门
忽略元数据末回到原数据开始处 MockServer介绍及文档 借鉴公司的文档 http://mock-server.com github:https://github.com/jamesdbloom/ ...
- MockServer的测试思想与实现
转载:http://blog.csdn.net/shen1936/article/details/50298901 背景 什么是MOCK Mock的定义 Mock框架简介 Mock在单测中的应用 De ...
- 使用Fiddler作为简单的mockserver
转载: http://blog.csdn.net/xt0916020331/article/details/66544526 开发中经常遇到调试过程中对接系统接口无法联调或者后台未开发完成等情况.这 ...
- postman里面的mockserver使用方法
转载:http://blog.csdn.net/Cloud_Huan/article/details/78326159 首先说下mockserver是干啥的,从英文翻译理解就是模拟一个服务器,通俗点说 ...
- MockServer jar包安装
github地址: https://github.com/jamesdbloom/mockserver 1. org.apache.maven.plugin-tools:maven-plugin-an ...
随机推荐
- 使用vue配合组件--转载
1.由饿了么 UED (知乎专栏)设计的桌面端组件库已经开源,文档:Element,仓库: GitHub - ElemeFE/element: Desktop UI elements for Vue. ...
- python-列表基本操作
本文讲解python列表的常用操作: 1.list函数,可以将任何序列作为list的参数 names=['lilei','tom','mackle','dongdong']print(list(nam ...
- 在Python中写入文件时,权限被拒绝错误
我想创建一个文件并在python中写一些整数数据.例如,我有一个变量abc = 3,我试图将它写入一个文件(它不存在,我假设python将自己创建): fout = open("newfil ...
- NSQ消息队列
前面的总结中提到过这个玩意,所以简单说说,win上面的测试验证 网上有比较合适的博文,我先推荐几篇 https://blog.csdn.net/a2247889821/article/details/ ...
- 对php引用的理解
/** * 引用是符号表别名 */ // $a与$b指向同一个变量 $a = &$b; // 定义函数foo,参数为引用类型:&$var,无函数体 function foo(& ...
- PHP 与Python 读取大文件的区别
php读取大文件的方法 <?php function readFile($file) { # 打开文件 $handle = fopen($file, 'rb'); while (feof($ ...
- [javase基础] JDK JRE JVM的区别?
JDK Java Development Kit 用作开发, 包含了JRE,编译器和其他的工具(比如: JavaDoc,Java调试器),可以让开发者开发.编译.执行Java应用程序. JRE Jav ...
- win10 + VS2015 编译 ARPACK
step 1: 下载ARPACK , mingw-w64-install 和 mingw-get-inst-20120426.exe: step 2: 安装 MinGW-64默认安装路径即可. ste ...
- python中map的排序以及取出map中取最大最小值
map排序: 1.按key排序: items=dict.items() items.sort() sorted(dict.items(),key=lambda x:x[0],reverse=False ...
- ceph学习笔记之十二 Ubuntu安装部署Ceph J版本
https://cloud.tencent.com/info/2b70340c72d893c30f5e124e89c346cd.html 安装Ubuntu系统安装步骤略过 拓扑连接: 一.安装前准备工 ...