mock测试【创建服务、fiddler、单元测试】 、开发mock平台
mock测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法。
一、创建服务的方式——flask、django
import flask from flask import request # 创建接口后台服务 server = flask.Flask(__name__) @server.route('/', methods=['get', 'post']) def demo(): # 获取get请求参数 arg = request.args.get("key") # post 获取表单请求数据 form = request.form.get("key", type=str, default=None) # 获取所有请求参数,不能获取json values = request.values.get("key") # 获取请求json json = request.get_json() print("arg", arg) print("form", form) print("values", values) print("json", json) return "你想返回的内容" server.run(host="127.0.0.1", port=9000, debug=True)
flask是python的一个轻量级web框架,比较简单。
django稍微比较复杂,可以参考:https://blog.csdn.net/weixin_30268071/article/details/98903930,这个已经做成了一个小项目的形式
遇到的问题:
1、post请求,结果获取参数的时候,却是如下方式
request.values.get("key")
2、post请求,因为Content-Type的问题,通过如下方式解决
request.get_json(force=True)
3、get请求,按道理参数是?后面拼接字段名=字段值,但是遇到的是直接放在/后面,解决示例如下
@server.route('/SeonRestService/email-api/v2.0/<email>', methods=['get']) def seon_email_api(email): """https://api.seon.io""" print("seon_email_api服务,email是:", email)
4、容器中安装vim
先执行:apt-get update
再执行:apt-get install vim
5、获取请求头,请求url,请求方法等信息都有对应的方法
6、接口返回的类型
https://www.cnblogs.com/xihuanniya/p/10451732.html
https://blog.csdn.net/qq_22034353/article/details/88758395
二、创建服务的方式—— tornado
tornado也是python自带的一个轻量级web框架,是一个群友提供的一个mock示例时,了解到的这个框架,可以参考:https://blog.csdn.net/xc_zhou/article/details/80637714
import tornado.ioloop import tornado.web class MainHandler(tornado.web.RequestHandler): '''http服务端''' def get(self): '''get请求''' a = self.get_argument('a') self.write({'我有这么多钱': int(a)}) def post(self): '''post请求''' h = self.request.headers u = self.request.uri b = self.request.body print("h", h) print("u", u) print("b", b) # 下面2行代码是设置返回的信息,目前没有想到使用场景 # self.set_header('Content-Type', 'application/json; charset=UTF-8;') # self.set_status(200, '失败') self.write("返回的内容") if __name__ == '__main__': application = tornado.web.Application([('/', MainHandler)]) # 默认host: 127.0.0.1 application.listen(address="127.0.0.2", port=8866) tornado.ioloop.IOLoop.instance().start() #和上面启动方式不同的地方就多了参数:decompress_request=True #在有这个配置项的时候,如果post请求的报文头部有说明编码方式是 gzip时,tornado将会对这个请求进行解压操作 # http_server = tornado.httpserver.HTTPServer(application, decompress_request=True) # http_server.listen(8866) # tornado.ioloop.IOLoop.instance().start()
三、fiddler的mock
实际上是劫持的方式给的自定义响应,如下图,在AutoResponder选项卡下添加规则即可
四、unittest中的mock
from unittest.mock import patch from unittest import mock import unittest class C: def a(self): return 666 def b(self): return 666 class TestXXX(unittest.TestCase): """单元测试的2种mock方式 mock不能凭空创建属性a,只能应用于对象逻辑还没完成但是需要这个对象的返回信息 感觉意义不是很大""" @patch.object(C, 'b') @patch.object(C, 'a') def test_xxx1(self, a, b): # 注意测试方法中的参数和装饰器的参数对应关系 a.return_value = 20 b.return_value = 30 c = C() print("test_xxx1", c.a(), c.b()) def test_xxx2(self): c = C() c.a = mock.Mock(return_value=20) print("test_xxx2", c.a()) if __name__ == '__main__': unittest.main()
五、java中的mock
package yin.service; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; // mock用到的2个包 import org.mockito.Mockito; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import yin.dao.StudentDao; import yin.domain.Student; import static org.junit.jupiter.api.Assertions.*; @SpringBootTest class StudentServiceTest { @Autowired StudentService studentService; @MockBean StudentDao studentDao; @BeforeEach void setUp() { // 下面studentService.getStudentById(1)中会用studentDao.getStudentById(1) Mockito.when(studentDao.getStudentById(1)). thenReturn(new Student(1,10,"whitewall")); } @Test void getStudentById() { Student student = studentService.getStudentById(1); assertNotNull(student); assertEquals(student.getAge(),12); } }
四、开发mock平台
get路径 https://域名/mock/cmdb/project_A/interface_A/get?page=1&pageSize=10 post路径 https://域名/mock/cmdb/project_A/interface_B/post
1、代码思路
mock接口格式(接收get、post):@app.route('/mock/<project>/<interface>/<request_type>')
先获取项目名/接口名/请求类型,判断是否在数据库中有匹配数据
然后判断请求类型
post请求会去获取请求体中的参数,然后跟进数据库中比较类型,去判断参数
get请求会去获取url后续的参数,然后跟进数据库中比较类型,去判断参数
2、建表
(1)项目表(项目id,项目名,项目描述,创建人,创建时间,修改人,修改时间)
(2)接口表(项目id,接口名,接口描述,场景说明,请求类型,比较类型(包含、恒等),入参,期望出参,是否有效,创建人,修改人,修改人,修改时间)
3、页面
(1)项目管理:项目增删查改
(2)接口管理:接口增删查改
a、一个接口可以对应多个场景
b、查询功能:项目查询、接口名、请求类型、是否生效(默认生效)
查询结果: 项目名、接口名、接口描述、场景说明、请求类型、入参、期望出参
查询结果操作:失效接口显示生效按钮、生效接口显示失效按钮、详情、编辑
c、新建、编辑功能:对应接口表的信息