基于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'))

指导说明

  1. 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报文

 

 
  1. 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": "注册成功啦" } }

  2. example for put

     

    json { "data": { "identity": { "equals": "1", "type": "string" } }, "invalid": { "equals": { "msg": "啊哦 该账号没有记录哦" }, "type": "类型不匹配啊" }, "method": "put", "name": "更新接口", "url": "/put/", "valid": { "msg": "查询成功啦", "success": true } }

  3. 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的理解自己可能也有偏差,所以还请各位大神不要见怪

本地开发环境部署

  1. git clone 或者 checkout至本地目录
  2. 修改:MockServer/config.py 数据库相关配置 python USERNAME = 'root' PASSWORD = 'lcc123456' HOST = '127.0.0.1' DB = 'MockServer'
  3. 安装相应依赖库 bash pip install -r requirements.txt
  4. 创建MockServer数据库, 默认DB是MockServer
  5. 生成数据库迁移脚本,应用表结构 bash python manage.py db init python manage.py db migrate python manage.py db upgrade
  6. Start Server bash python run.py

MockServer的更多相关文章

  1. mockServer学习

    mockServer学习 很喜欢mockserver官方主页的背景颜色和格式 官方主页如下: http://www.mock-server.com/

  2. 【Mock】【接口测试】【面试】mock-server 环境搭建—加分项!

    mock-server 环境搭建 前言 mock 除了用在单元测试过程中,还有一个用途,当前端开发在开发页面的需要服务端提供 API 接口 此时服务端没开发完成,或者说没搭建测试环境,这个时候前端开发 ...

  3. 【Mock】mock-server 环境搭建

    前言 mock 除了用在单元测试过程中,还有一个用途,当前端开发在开发页面的时候,需要服务端提供 API 接口 此时服务端没开发完成,或者说没搭建测试环境,这个时候前端开发会自己 mock一个 api ...

  4. 使用mockserver来进行http接口mock

    转载自:https://blog.csdn.net/heymysweetheart/article/details/52227379:(注,这个不是很符合我的要求,它主要的作用是可以通过简单的代码就能 ...

  5. nodejs结合apiblue实现MockServer

    apiblue功能很强大,里面支持很多插件,这些插件能够为restfulAPI提供接口文档自动生成,甚至Mockserver的功能,当然,好多插件还是有很多坑的.下面用apiblue实现下面的业务需求 ...

  6. MockServer 入门

    忽略元数据末回到原数据开始处 MockServer介绍及文档 借鉴公司的文档 http://mock-server.com github:https://github.com/jamesdbloom/ ...

  7. MockServer的测试思想与实现

    转载:http://blog.csdn.net/shen1936/article/details/50298901 背景 什么是MOCK Mock的定义 Mock框架简介 Mock在单测中的应用 De ...

  8. 使用Fiddler作为简单的mockserver

    转载:  http://blog.csdn.net/xt0916020331/article/details/66544526 开发中经常遇到调试过程中对接系统接口无法联调或者后台未开发完成等情况.这 ...

  9. postman里面的mockserver使用方法

    转载:http://blog.csdn.net/Cloud_Huan/article/details/78326159 首先说下mockserver是干啥的,从英文翻译理解就是模拟一个服务器,通俗点说 ...

  10. MockServer jar包安装

    github地址: https://github.com/jamesdbloom/mockserver 1. org.apache.maven.plugin-tools:maven-plugin-an ...

随机推荐

  1. addr2line探秘 [從ip讀出程式中哪行出錯]

    addr2line探秘 在Linux下写C/C++程序的程序员,时常与Core Dump相见.在内存越界访问,收到不能处理的信号,除零等错误出现时,我们精心或不精心写就的程序就直接一命呜呼了,Core ...

  2. 如何用Mybatis分库分表

    分库 在分库的时候 有时候为了方便 一些表需要存放所有库的信息,称为全局库.如:用户表存放所有的用户. 此时分库的思路 数据库分为全局库和业务库,其中业务库又分为N多个库,全局库只放个别表方便开发. ...

  3. Js event对象offsetX,pageX,screenX,clientX详解

       平时在测量元素位置时难以确定,下面给出具体的event对象中的各种属性,以便日后使用.   检测相对于浏览器的位置:clientX和clientY     当鼠标事件发生时,鼠标相对于浏览器左上 ...

  4. JQuery 获取表格table所有行第一列

    main_table 是表ID $("#main_table tr").find("td:eq(0)")

  5. redis基础及基本命令

    什么是redis Redis是一个Key-value存储系统,redis提供了丰富的数据结构,包括string(字符串),list(列表),sets(集合),ordered set(有序集合),has ...

  6. Vue-cli的安装步骤详细版本

    https://github.com/vuejs/vue-cli 官网 使用官方推荐的webpack 条件:node在4.以上,npm在3以上 安装步骤:1.cmd打开命令行窗口2.输入cnpm in ...

  7. [BOOKS]BIG DATA and DATA ANALYTICS: The Beginner's Guide to Understanding the Analytical World

  8. leetcode-165周赛-1276-不浪费原料的汉堡制作方案

    题目描述: 自己的提交: class Solution: def numOfBurgers(self, tomatoSlices: int, cheeseSlices: int) -> List ...

  9. Docker 镜像添加模块

    Docker 镜像添加模块   1. 使用root用户进入一个新容器,不要用 --rm .否则退出容器的时候,容器没有了 docker run --user 0 -it --name superman ...

  10. PHP发送公众号模板消息

    <?php /* * 模板消息发送,电脑端测试时需要手动填写openid * 微信端会自动获取当前openid发送无需填写 */ header("Content-type: text/ ...