Mock服务的作用
现今的业务系统很少有孤立存在的,它们或多或少需要使用兄弟团队或是其他公司提供的服务,给我们的联调和测试造成了麻烦。对于这种情况,我们常见的解决方案是搭建一个临时的server,模拟那些服务,提供数据进行联调和测试。这就是 mock server 出现原因。
应用场景
- 在前后端分离的项目中,假如后端代码还未开发完,前端代码需要调用后端接口进行调试,该怎么办?
- 本公司的电商平台需要对接第三方支付接口,如何测试支付失败的场景?
接口测试中Mock的用处
- 客户端/前端开发联调前置,在接口未开发完成的情况下,需要等待接口的数据来进行开发,这时候完善的接口Mock服务能大大缩短开发联调等待时间。
- 接口集成测试,部分依赖服务未完成前,利用Mock完成本身的接口开发/测试。
- 复杂的场景模拟,复现验证bug的时候,需要先准备比较复杂的数据场景,才能复现一个bug。此时,Mock的定制返回,节省了大量数据准备的时间,直接可复现和验证bug
- 测试时,异常场景的模拟,如长字符串,负数,异常返回等。
*比如app页面的健壮性mock模拟。
*比如模拟接口超时返回。 - 需要测试真实支付场景时,可以mock支付接口或使用相应的沙箱环境。
- 性能测试中隔离第三方接口 – 经常会遇到一些接口去调用其他服务接口,或者调用第三方接口。在进行压测的时候就会遇到问题,因为很难隔离掉其他服务和第三方接口的性能变化情况—响应时间不稳定。这时可以mock一个固定TPS的外部接口。
python代码实现flask模块
1、mock服务本质:就是自己写一个接口,返回规定的响应数据
2、使用Python代码实现flask模块 pip install flask
- 通过装饰器
@app.route(url, 请求参数)
来定义URL地址 - 第一个参数是定义的URL,第二个参数时请求方法,不写默认是get方法
3、获取请求参数
(1)post请求: methods=[‘post’]
- 请求参数是json类型:
request.get_json()
返回值是字典 - 请求参数是form表单类型:
request.form.to_dict()
(2)get请求:request.args.to_dict()
@app.route('/login', methods=['POST', 'GET']) # 既支持post接口,也支持get接口
# @app.route('/login', methods=['POST']) # 只支持post接口
def login():
'''
json类型的数据
:return:
'''
# data = request.get_json() # 请求参数是json的数据
# data = request.form.to_dict() # 请求参数是form-data的数据
data = request.args.to_dict() # get请求参数的数据
# 主要做逻辑判断
return jsonify({
'code': 10001,
'msg': 'success',
'data': data
})
4、返回的资源,响应
(1)return 字符串
@app.route('/index')
def index(): # 定义一下/index这个url地址返回的资源是什么
return 'hello world'
(2)jsonify() 返回json数据
@app.route('/login', methods=['POST', 'GET']) # 既支持post接口,也支持get接口
# @app.route('/login', methods=['POST']) # 只支持post接口
def login():
'''
json类型的数据
:return:
'''
# data = request.get_json() # 请求参数是json的数据
# data = request.form.to_dict() # 请求参数是form-data的数据
data = request.args.to_dict() # get请求参数的数据
# 主要做逻辑判断
return jsonify({
'code': 10001,
'msg': 'success',
'data': data
})
(3)redirect(url_for(获取资源的函数名字)) 重定向
@app.route('/demo')
def demo():
return redirect(url_for('index'))
(4)自己构造响应 make_response()
@app.route('/login2')
def login2():
resp = make_response(redirect(url_for('index')))
# 给响应设置cookie值,set_cookie进行一个设置
# 响应.set_cookie(键,值)
resp.set_cookie('testfan-id', '234354353434534')
return resp
@app.route('/query')
def query():
# request.cookies 类似字典,获取所有的cookie值
data = request.cookies.get('testfan-id')
return jsonify({
'code': 10001,
'msg': 'success',
'data': data
})
(5)前后端不分离想写页面 render_template(xxx.html)
5、获取动态路由,<变量> 默认变量是字符串类型<int:变量>
变量是int类型
@app.route('/<func>', methods=['POST'])
def register(func):
data = request.get_json()
if func == 'register':
resp = passThroughRe(data)
return resp
moco框架搭建mock服务
1、Moco运行时所需环境包括:
- Java运行环境:安装JDK,并配置环境变量
- 下载jar包 :moco-runner-1.1.0-standalone.jar
下载地址:jar包下载地址
2、如何运行moco
(1)进入jar包所在目录,创建配置文件test.json
[
{
"description": "首页",
"request": {
"uri": "/index"
},
"response": {
"text": "hello world"
}
}
]
(2)启动http服务
启动命令:
java -jar <path-to-moco-runner> start -p <monitor-port> -c <configuration-file>
java -jar moco-runner-<version>-standalone.jar start -p 端口号 -c ***.json
<path-to-moco-runner>
:jar包的路径<monitor-port>
:http服务监听的端口<configuration-file>
:配置文件路径
(3)接口访问
打开浏览器,在浏览器地址栏中输入:http://127.0.0.1:9090/index
3、Moco常用配置参数
(1)通过method参数定义请求方式
[
{
"description": "首页",
"request": {
"uri": "/index",
"method": "post"
},
"response": {
"text": "hello world"
}
}
]
(2)定义请求参数
get请求:通过queries定义请求参数
[
{
"description": "首页",
"request": {
"uri": "/index",
"method": "get",
"queries": {
"username": "haha",
"password": "123456"
}
},
"response": {
"text": "hello world"
}
}
post请求:
- 通过forms参数定义表单请求体
[
{
"description": "登录",
"request": {
"uri": "/login",
"method": "post",
"forms": {
"username": "tom",
"password": "123456"
}
},
"response": {
"text": "login success"
}
}
]
- 通过json参数定义json请求体(request中)
[
{
"description": "登录",
"request": {
"uri": "/login",
"method": "post",
"json": {
"username": "tom",
"password": "123456"
}
},
"response": {
"text": "login success"
}
}
]
(3)通过headers参数定义请求头
[
{
"description": "登录",
"request": {
"uri": "/login",
"method": "post",
"headers": {
"test": "aaa"
}
},
"response": {
"text": "hello world"
}
}
]
(4)通过status参数定义HTTP响应状态码
[
{
"description": "登录",
"request": {
"uri": "/login2"
},
"response": {
"status": 500,
"text": "error"
}
}
]
(5)通过json参数定义json响应数据(response中)
[
{
"description": "登录",
"request": {
"uri": "/login",
"method": "post",
"json": {
"username": "haha",
"password": "123456"
}
},
"response": {
"json": {
"code": "1001",
"msg": "login success",
"data": {
"username": "haha",
"uid": 2,
"token": "xadsfewfdvsjkhilh"
}
}
}
}
]
(6)Moco提供了template功能,可以动态的返回一些参数值
[
{
"description": "登录",
"request": {
"uri": "/login",
"method": "post",
"json": {
"username": "haha",
"password": "123456"
}
},
"response": {
"text": {
"template": "${req.json['username']}"
}
}
}
]
4、redirect重定向
[
{
"description": "首页",
"request": {
"uri": "/index",
"method": "get"
},
"redirectTo": {
"text": "http://www.baidu.com"
}
}
]
5、moco引入配置文件
moco支持在配置文件中引入其他配置文件,这样可以分服务/模块定义配置文件,便于对配置文件的管理。
实现步骤如下:
(1)分服务/模块定义配置文件,如:分别定义index.json
和login.json
文件
index.json
[
{
"description": "首页",
"request": {
"uri": "/index",
"method": "get"
},
"response": {
"text": "hello world"
}
}
]
login.json
[
{
"description": "登录",
"request": {
"uri": "/login",
"method": "post",
"json": {
"username": "haha",
"password": "123456"
}
},
"response": {
"json": {
"code": 1001,
"msg": "success",
"data": {
"username": "haha",
"uid": 2,
"token": "xadsfewfdvsjkhilh"
}
}
}
}
]
(2)定义启动配置文件,如config.json
,并引入其他配置文件
[
{"include": "index.json"},
{"include": "login.json"}
]
(3)启动服务
java -jar moco-runner-1.1.0-standalone.jar start -p 9090 -g config.json
注意:通过-g config.json
指定配置文件
mock服务知识思维导图