一、 背景

福禄网络作为一家数字权益商品及服务提供商,覆盖了我们衣食住行的各种生活场景的权益内容,对接了如支付宝、京东、银行APP各种渠道,如何能够快速的响应渠道需求,提供稳定的接口服务,这就要求我们电商团队能够做到比渠道快一步的接口测试;

同时作为一家集团化的公司,内部的信息化系统对接了众多银行的相关支付业务,涉及到查余额、下流水、支付、对账等日常资金业务,这要求信息化部门能够确保资金支付相关场景能够在上线前进行完整覆盖,业务方新的业务接入或者需求场景变更比较频繁,版本的快速迭代背景下如何保证众多的场景能够快速覆盖,通过完全真实的业务操作成本是巨大的;

二、 引入MOCK

基于上述的业务系统测试痛点,质量管理团队决定引入mock服务。我们首先想到的是以最低的成本来完成,市面上有许多的mockserver的开源软件,但在调研了相关的开源产品之后,我们发现没有一款比较贴合我们业务需求的产品;

比如我们的资金支付相关场景对接的银行方,都是以xml报文的格式作为请求和返回;有些场景对返回模板的数据是动态要求的,比如某个支付状态第一次请求是处理中,第N次请求变为成功;而有些银行通信协议是socket等,通过调研后我们决定自己来开发一套mock服务。

三、框架选型

  1. 界面可视化操作

    为了保持系统风格的统一,我们决定沿用QECS平台的前端框架(QECS详细介绍移步至:https://www.cnblogs.com/fulu/p/15419208.html)
  2. 高性能

    为了满足高性能的需求,模板数据存储我们采用redis;开始我们准备沿用QECS的后端框架flask,在进行了一系列的性能测试后,我们发现无法支撑我们5KTPS的需求,后来我们改用了springBoot,经过测试能够达到我们的需求;

四、具体实现

4.1 设计方案



外部请求打入Mock服务,监听服务获取到请求通过Redis中的已有模板进行规则匹配,满足匹配规则返回对应模板数据;不满足返回无法匹配的数据提示。

4.2 功能说明

数据格式

目前匹配规则支持json、form、query、xml这几种参数类型;返回支持json、xml和text这几种数据类型

状态码

可以模拟返回200、500、304、502、503、400等各种http状态码

返回时间

可以设置请求mock服务后的返回间隔时间,对超时返回场景比较有效

动态取值

设置了内置函数和从匹配规则中取值这两种方式,可以动态设置返回数据的字段值

自定义代码

对于平台界面暂时无法支撑的个性化需求,可以通过在Hermes中通过代码来实现,灵活方便

高性能

模板数据通过Redis进行存储,请求进来到模拟返回通过redis进行匹配,能够提供高性能的返回,可作为性能压测的挡板服务

4.3 平台功能介绍



4.3.1 主界面

4.3.2 创建API,即我们需要模拟调用的对方接口

4.3.3 配置模板,配置API的期望模板



模板数据会存储到REDIS

4.3.4 模拟请求

获取实际请求值,获取期望模板值,将模板与请求值进行比较匹配,当模板请求参数属于真实请求参数的子集,匹配成功

4.3.5 自定义函数的实现

为了满足个性化的使用场景,服务内置了一批内置函数来满足动态取值的场景

private static String getReplaceStr(String str){
if(str.contains("Random")){
String[] strA = str.trim().split(",");
int i1 = strA[0].indexOf("(");
int i2 = strA[1].indexOf(")");
String min = strA[0].substring(i1+1);
String max = strA[1].substring(0,i2);
return getRandom(Integer.valueOf(min), Integer.valueOf(max)).toString();
}
if(str.contains("CurrentDate")){
return getCurrentDate();
}
if(str.contains("SecondTime")){
return getSecondTime().toString();
}
if(str.contains("MicTime")){
return getMicTime().toString();
}
if(str.contains("CardID")){
return getCardID();
}
if(str.contains("Phone")){
return getPhone();
}
return str;
}



4.3.6 专家模式,对于目前界面暂时无法支撑的个性化需求,我们采取通过在后端服务编码的方式进行处理

@RequestMapping(value = {"/test"})
public void loadNum(HttpServletRequest request, HttpServletResponse httpServletResponse){
TimerTool timerTool = new TimerTool();
RestfulRequest restfulRequest = requestService.analyseRequest(request);
restfulRequest = filterHeader(restfulRequest);
log.info("分析请求cost:{}", timerTool.cut()); List<MockInfo> mockRules = mockInfoService.getMockRules(restfulRequest.getPath());
log.info("获取mock配置记录:{}, cost:{}", mockRules, timerTool.cut()); MockInfo mockRule = mockService.matchRulesNew(restfulRequest, mockRules);
log.info("匹配tag...cost:{}", timerTool.cut());
//先走平台模板,如果匹配不到,走专家模式(代码实现)的MOCK匹配逻辑
if(mockRule != null){
mockService.doResponseNew(mockRule, httpServletResponse);
}else {
mockExpertService.doResponse(restfulRequest, httpServletResponse);
}
}

专家模式实现个性化的mock逻辑

public void doResponse(RestfulRequest request, HttpServletResponse response){
try { RestfulBody body = request.getBody();
String ip = request.getIp();
JSONObject requestParams = body.getParams();
String funName = requestParams.getJSONObject("CMBSDKPGK").getJSONObject("INFO").getString("FUNNAM"); Integer responseStatus = 200 ;
Integer responseSleep = 0;
String responseString = "mock数据去火星了!";
String responseInfo = mockInfoService.getMockExpert(ip,funName);
JSONObject responseInfoJson; if(StringUtils.isEmpty(responseInfo)){
responseInfoJson = new JSONObject(true);
responseInfoJson.put("count", 0);
responseInfoJson.put("firstTime", TimeUtils.nowTimeStamp() / 1000);
responseInfoJson.put("response", getJsonResponse("xmlResource/resp_" + funName + ".xml"));
}else {
responseInfoJson = JSONObject.parseObject(responseInfo);
}
int count = responseInfoJson.getInteger("count");
JSONObject responseObj = responseInfoJson.getJSONObject("response");
// 批量查询余额
if("NTQADINF".equals(funName)){
long time_lag = (TimeUtils.nowTimeStamp() / 1000) - responseInfoJson.getLong("firstTime");
Object obj = responseObj.getJSONObject("CMBSDKPGK").get("NTQADINFZ");
// 距离第一次请求超过60s 余额+5000
if(time_lag > 60){
if(obj instanceof JSONArray){
JSONArray jsonA = (JSONArray)obj;
for(int i=0; i<jsonA.size();i++){
Double avlblv_value = jsonA.getJSONObject(i).getDoubleValue("AVLBLV");
avlblv_value = avlblv_value + 5000;
jsonA.getJSONObject(i).put("AVLBLV", String.format("%.2f",avlblv_value));
}
responseObj.put("NTQADINFZ", jsonA);
}
if(obj instanceof JSONObject){
JSONObject jsono = (JSONObject)obj;
Double avlblv_value = jsono.getDoubleValue("AVLBLV");
avlblv_value = avlblv_value + 5000;
jsono.put("AVLBLV", String.format("%.2f",avlblv_value));
responseObj.put("NTQADINFZ", jsono);
}
}
};

五、未来展望

目前这个版本我们适配了http协议下的大部分数据格式,如上所述,对于一些个性化的需求我们暂时采取的专家模式代码实现,一方面体现了自有平台的灵活性,另一方面我们也会在不断的使用过程中进行抽象提炼成共性的需求继续可视化的实现。

内置函数随着平台的使用范围和深度,相信会有更多需求场景需要相关函数的实现加以满足,不断去丰富这些函数,也是平台健壮的一个表现;

另外对于其他相关协议的补充也是平台需要进行后续规划完善的发力点。

你们有哪些mock的实际使用场景,欢迎交流

福禄·研发中心
福小龙

质量体系建设之路---可视化的MockServer的更多相关文章

  1. 质量保障&&质量体系建设

    一.质量保障 先引用一段 百度百科 上对软件质量保障的解释:软件质量保障是建立一套有计划,系统的方法,来向管理层保证拟定出的标准.步骤.实践和方法能够正确地被项目所采用.软件质量保证的目的是使软件过程 ...

  2. 民生银行十五年的数据体系建设,深入解读阿拉丁大数据生态圈、人人BI 是如何养成的?【转】

    早在今年的上半年我应邀参加了由 Smartbi 主办的一个小型数据分析交流活动,在活动现场第一次了解到了民生银行的阿拉丁项目.由于时间关系,嘉宾现场分享的内容非常有限.凭着多年对行业研究和对解决方案的 ...

  3. 地图POI类别标签体系建设实践

    导读 POI是“Point of interest”的缩写,中文可以翻译为“兴趣点”.在地图上,一个POI可以是一栋房子.一个商铺.一个公交站.一个湖泊.一条道路等.在地图搜索场景,POI是检索对象, ...

  4. Atitit 项目中的勋章体系,,mvp建设 ,荣典体系建设

    Atitit 项目中的勋章体系,,mvp建设 ,荣典体系建设 1. 荣典体系的标准1 2. 勋章称号1 2.1.1. 授予标准1 3. 政出多门  统一的荣誉制度 2 3.1. 法则规定2 3.2. ...

  5. 【行业交流】2016 TiD质量竞争力大会——移动互联网测试到质量的转变之路

    ◆版权声明:本文出自胖喵~的博客,转载必须注明出处. 转载请注明出处:http://www.cnblogs.com/by-dream/p/5691233.html TiD质量大会在北京召开,有幸去参加 ...

  6. Hi,这有一份风控体系建设干货

    互联网.移动互联网.云计算.大数据.人工智能.物联网.区块链等技术已经在人类经济生活中扮演越来越重要的角色,技术给人类带来各种便利的同时,很多企业也饱受"硬币"另一面的伤害,并且形 ...

  7. 如何推进企业流程体系建设?_K2 BPM

    推进全集团统一的流程体系为什么比想象的难? 很多企业在推进全集团的流程管理过程中,经常会有一种“望山跑死马”的感觉.“各成员公司都建立起与集团公司统一的流程管理体系”,看似很简单一件事情,但没有经过良 ...

  8. Atitit 快速开发体系建设路线图

    Atitit 快速开发体系建设路线图 1.1. 项目类型划分 哑铃型 橄榄型  直板型(可以立即实行)1 1.2. 解决方案知识库 最佳实践库 最佳流程优化(已成,需要一些整理)2 1.3. 功能模板 ...

  9. Atitit 提升效率 界面gui方面的前后端分离与cbb体系建设 规范与推荐标准

    Atitit 提升效率 界面gui方面的前后端分离与cbb体系建设 规范与推荐标准 1. 界面gui方面的前后端分离重大意义1 2. 业务逻辑也适当的迁移js化1 3. 常用分离方法2 3.1. 页面 ...

随机推荐

  1. WebGL着色器渲染小游戏实战

    项目起因 经过对 GLSL 的了解,以及 shadertoy 上各种项目的洗礼,现在开发简单交互图形应该不是一个怎么困难的问题了.下面开始来对一些已有业务逻辑的项目做GLSL渲染器替换开发. 起因是看 ...

  2. Golang通脉之并发初探

    并发是编程里面一个非常重要的概念,Go语言在语言层面天生支持并发. 并发与并行 并发:同一时间段内执行多个任务. 并行:同一时刻执行多个任务,有时间上的重叠. 进程.线程.协程 进程(Process) ...

  3. 洛谷 P5785 [SDOI2012] 任务安排

    链接: P5785 弱化版:P2365 题意: 有 \(n\) 个任务待完成,每个任务有一个完成时间 \(t_i\) 和费用系数 \(f_i\),相邻的任务可以被分成一批.从零时刻开始这些任务会被机器 ...

  4. IDEA插件开发,我是如何把公司的发布系统搬到IDEA里的

    不得不说JetBrains公司直的非常的牛B,每一个程序员都能在JetBrains的官方网站找到一款属于自己的开发工具.这些开发工具在工作中给我们带来了巨大的便利.各种各样的基础插件,第三方插件,真是 ...

  5. 数字设计中的时钟与约束(gate)

    转载:https://www.cnblogs.com/IClearner/p/6440488.html 最近做完了synopsys的DC workshop,涉及到时钟的建模/约束,这里就来聊聊数字中的 ...

  6. Github图床设置

    创建新仓库 点击右上角加号->新建仓库,填写基本信息后点击下面的创建即可 https://github.com/new 创建新令牌 点击设置->开发者设置->私人令牌->生成新 ...

  7. 中文NER的那些事儿4. 数据增强在NER的尝试

    这一章我们不聊模型来聊聊数据,解决实际问题时90%的时间其实都是在和数据作斗争,于是无标注,弱标注,少标注,半标注对应的各类解决方案可谓是百花齐放.在第二章我们也尝试通过多目标对抗学习的方式引入额外的 ...

  8. Java项目中集成钉钉机器人推送消息提醒

    前言: 项目中有一个需求,当有新订单产生的时候,希望能够及时通知到业务相关人员进行处理,整体考虑了一下,选用了钉钉机器人提醒功能(公司内部主要也是使用钉钉进行通讯). 操作: 主要分为两部分进行处理: ...

  9. 议题解析与复现--《Java内存攻击技术漫谈》(二)无文件落地Agent型内存马

    无文件落地Agent型内存马植入 可行性分析 使用jsp写入或者代码执行漏洞,如反序列化等,不需要上传agent Java 动态调试技术原理及实践 - 美团技术团队 (meituan.com) 首先, ...

  10. 攻防世界 WEB 高手进阶区 upload1 Writeup

    攻防世界 WEB 高手进阶区 upload1 Writeup 题目介绍 题目考点 文件上传漏洞 一句话木马 中国菜刀类工具的使用 Writeup 使用burpsuite抓包 可见只是对上传文件的后缀进 ...