基于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. 创建网关项目(Spring Cloud Gateway)

    创建网关项目 加入网关后微服务的架构图 创建项目 POM文件 <properties> <java.version>1.8</java.version> <s ...

  2. C++中继承的protected访问级别

    1,子类是否可以直接访问父类的私有成员? 2,根据面向对象理论: 根据 C++ 语法: 3,继承中的访问级别编程实验: #include <iostream> #include <s ...

  3. 自增主键与UUID的优缺点

    自增主键 自增ID是在设计表时将id字段的值设置为自增的形式,这样当插入一行数据时无需指定id会自动根据前一字段的ID值+1进行填充.在MySQL数据库中,可通过sql语句AUTO_INCREMENT ...

  4. Ubuntu下使用git clone 的权限问题解决方法

    问题1.sign_and_send_pubkey: signing failed: agent refused operation,执行如下语句: eval "$(ssh-agent -s) ...

  5. 【知识强化】第四章 网络层 4.4 IPv4

    这节课我们来学习一个非常重要的概念,就是IPv4地址,其实也是我们常用的IP地址. 首先我们来了解一下,为什么会有IP地址的出现以及它是做什么用的.假如说在很多年前我遇到一个女生非常的漂亮,等了十年之 ...

  6. IntelliJ Idea 环境搭建

    安装IntelliJ Idea 可以去官网下载: https://www.jetbrains.com/idea/download/#section=windows 选择Ultimate.一路下一步安装 ...

  7. linux100day(day6)--shell脚本简单逻辑

    if语句: if条件语句的使用格式: 1.单分支语句 if 条件;then 执行语句 fi 2.双分支语句 if 条件;then 执行语句1 else 执行语句2 fi 3.多分支语句 if 条件;t ...

  8. Linux历史命令管理以及用法

    history [-c] [-d offset] [n] history -anrw [filename] history -ps arg [arg...] -c: 清空命令历史 -d offset: ...

  9. java--ArrayList,LinkedList应用比较

    import java.util.ArrayList; import java.util.LinkedList; import java.util.List; public class ListDem ...

  10. 【CSS】position(定位)属性

    关于CSS position,来自MDN的描述: CSS position属性用于指定一个元素在文档中的定位方式.top.right.bottom.left 属性则决定了该元素的最终位置. 然后来看看 ...