前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Web技术】321- 花椒接口Mock方案

【Web技术】321- 花椒接口Mock方案

作者头像
pingan8787
发布2019-08-20 12:03:28
6920
发布2019-08-20 12:03:28
举报
文章被收录于专栏:前端自习课前端自习课

什么是Mock?

 Mock是指在测试过程中,对于一些不容易构造/获取的对象,创建一个mock对象来模拟对象的行为。早期mock多被用于单元测试/接口测试中,被测试对象依赖其他对象,且这些对象的构造复杂、耗时或者根本无法构造(未交付), 对于单个测试对象,假定其依赖对象的逻辑正确,我们只需要保证测试模块内部逻辑的质量即可。本文主要讲述web接口的mock。

接口Mock用处?

 在实际的软件开发过程中,我们的链路往往是:服务业务A->服务业务B->客户端/前端->测试,整个开发周期里,业务B的人依赖业务A才能联调提测,客户端/前端依赖B的接口有数据后才能开发新的功能,Mock很好缩短了这个过程中等待的时间。

1. 客户端/前端开发联调前置,现今移动端的app多依赖服务端接口的返回来开发app的页面,在接口未开发完成的情况下,需要等待接口的数据来进行开发,这时候完善的的接口mock服务能大大缩短开发联调等待时间。

2. 接口集成测试,部分依赖服务未完成前,利用mock完成本身的接口开发/测试

3. 复杂的场景模拟,复现验证bug的时候,需要先准备比较复杂的数据场景,才能复现一个bug,此时,mock的定制返回,节省了大量数据准备的时间,直接可复现和验证bug

4. 测试时,异常场景的模拟,如长字符串,负数,异常返回等

花椒的Mock方案

 说了这么多,我们来说说花椒的接口Mock方案。传统的接口mock服务弊端有:

1. 需要绑定接口请求的业务服务到指定的mock服务,这样需要wifi的host不停更改,或本机的host不停更改,来切换正常环境和mock环境

2. 绑定host因为是整个域名绑定到mock服务,如果其他接口没有mock会导致很多接口不可用,而走不到想走的场景,且多人公用wifi的情况下,会互相影响

3. 不同的用户对同一接口的请求,期望的返回不一样,无法对用户定制化,也即同时只能满足一个开发或测试人员的mock需求

4. 传统的mock服务大多采用文件编辑mock数据,不易编辑管理

 考虑到上述弊端,我们的接口Mock服务,设计的初衷有以下几点:

1. 如何让客户端/前端开发人员简单易用,不需要太多环境的设置,保证用户能在正式环境和mock环境之间切换

2. 如何支持多用户同时使用,且mock数据不一样的需求

3. 花椒的部分服务是有加解密的,返回的数据是一堆加密串,如何更方便的编辑管理mock返回数据

 花椒的接口mock方案, 主要是采用业务服务器跳转 + mock服务 + 后台管理,同时支持传统的mock服务的使用方式。

Mock1

主要有如下三部分组成:

* Mock后台

 Mock后台是整个mock服务的配置中心, 用户在后台定制自己的接口mock数据,配置需要跳转的用户及接口。开发框架用的是springboot + mybatis + vue,前端页面和后端服务剥离,springboot提供操作数据库的接口给前端vue页面调用,主要文件目录一个vueMockController, 一个数据库操作文件MockMapper,文件目录非常简单,主要功能有:

1. 展示用户的所有mock数据,支持根据作者查询,uri查询,模块查询

代码语言:javascript
复制
/按Uri查找数据
@RequestMapping("findByUri")
public RestResult findByUri(@RequestBody JSONObject request) throws Exception {
    int offset = request.getIntValue("offset");
    String uri = request.getString("uri");
    uri = "%" + uri + "%";
    List<MockData> data = mapper.getMockDataByUri(uri, offset);
    for (MockData one : data) {
        one.decryptData();
    }
    int total = mapper.getMockDataByUriTotal(uri);
    return success(formatPageData(data, total, offset));
}

2. 支持新增,删除、编辑mock数据功能,写入数据根据选择的平台ios/android,判断有无加密,有加密按各自的加密key加密后写requset和response数据到数据库

主要数据库信息如下, encrypt是否加密,platform(请求客户端iOS或Android),model为模块,uid为用户私有标识,request为请求参数(同时支持key=value的form数据,{“key”:“value”}的json数据),response为响应数据

代码语言:javascript
复制
TABLE `mock` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `uri` varchar(255) DEFAULT NULL,
  `request` varchar(500) CHARACTER SET utf8mb4 DEFAULT NULL,
  `response` text CHARACTER SET utf8mb4,
  `statusCode` int(11) DEFAULT NULL,
  `platform` varchar(20) CHARACTER SET utf8mb4 DEFAULT NULL,
  `encrypt` tinyint(1) DEFAULT NULL COMMENT '0无 1经济 2底层',
  `model` varchar(20) CHARACTER SET utf8mb4 DEFAULT NULL,
  `author` varchar(20) CHARACTER SET utf8mb4 DEFAULT NULL,
  `moduser` varchar(20) CHARACTER SET utf8mb4 DEFAULT NULL,
  `server` tinyint(1) unsigned DEFAULT NULL,
  `method` tinyint(1) unsigned DEFAULT NULL COMMENT '0Get 1Post',
  `uid` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL,
)

对应的页面展示如下,同时提供了加完数据后运行查看是否mock成功的功能.

mock3

3. 获取业务服务器所有mock配置,并展示,支持新增,编辑,修改后同步设置到业务服务器

mock2

* Mock Service

 Mock service是mock请求/返回处理的中心模块,主要逻辑是获取跳转过来的用户请求,处理请求数据,根据不同的请求参数,查询数据库里的配置数据,修改response数据为mock数据返回给用户。开发框架是基于git上开源项目moco的二次开发, Moco在git上的开源地址https://github.com/dreamhead/moco, 是一个简单搭建模拟服务器的程序库/工具, 基于java开发的,mock数据通过文件管理,使用方式很便捷简单,但由于本身花椒服务的特殊性,和考虑到可视化管理,我们对moco进行了二次开发,主要改动方向:

1. Mock数据管理新增数据库存储管理方式, mybatis连接数据库,新增一个数据库操作MockMapper文件,新增一个service方法来处理数据库查询合并结果,具体的mybatis的配置如下:

代码语言:javascript
复制
<configuration>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC" />
            <!-- 配置数据库连接信息 -->
            <dataSource type="POOLED">
                <property name="driver" value="com.mysql.jdbc.Driver" />
                <property name="url" value="jdbc:mysql://10.14.*.*:port/db_name?useUnicode=true&amp;characterEncoding=utf-8" />
                <property name="username" value="username" />
                <property name="password" value="password" />
            </dataSource>
        </environment>
    </environments>
    <mappers>
    <mapper class="com.github.dreamhead.moco.MockMapper"/>
    </mappers>
</configuration>

2. 请求处理适应花椒业务,url请求参数和post数据同时处理,匹配mock数据,以及匹配优先级等特殊处理

 修改moco-core工程里com.github.dreamhead.moco.internal下的MocoHandler.java方法doGetHttpResponse(),匹配规则:

  • 优先匹配用户私有的mock数据,uri(接口uri)+ platform + uid + request参数,有则返回
  • 其次匹配非用户私有的mock数据,uri(接口uri)+ platform + request参数,有则返回
  • 忽略请求参数匹配mock数据,uri(接口uri)+ platform,有则返回
  • 忽略端平台匹配mock数据,uri(接口uri),有则返回

此处之所以要做这么多优先级规则,是为了让使用mock服务的接口能正常匹配到数据,大部分使用者在初期并没有私有数据的需求,随着场景的加深,才会设计独有的数据,所以根据使用习惯,做了分层匹配

3. https的方案更改为nginx配置处理业务证书,证书验证剥离mock服务

java -jar mock-1.0.0-uber.jar http -p 3001 -c config.json //启动服务

本机nginx配置:

代码语言:javascript
复制
server {
        listen       443 ssl http2 default_server;
        server_name  *.*.com; //服务根域名
        root         /usr/share/nginx/html;

        ssl_certificate "/etc/nginx/ssl/tongpei.*.*.com_bundle.crt"; //证书
        ssl_certificate_key "/etc/nginx/ssl/tongpei.*.*.com.key"; //key
        ssl_session_cache shared:SSL:1m;
        ssl_session_timeout  10m;
        ssl_ciphers HIGH:!aNULL:!MD5;
        ssl_prefer_server_ciphers on;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;

        location / {
           proxy_pass http://127.0.0.1:3001; //跳转mock服务
        }

* 业务服务器跳转处理

 此处的业务服务器是app应用/前端实际使用的服务器,比如登陆服务。业务服务器的跳转处理,主要是根据用户的请求,判断是否需要跳转到mock服务。逻辑处理是在nginx层处理的,用的luascript,提供了两个接口,一个lua/pour,用于提供给mock后台来设置跳转信息,写到Nginx缓存里;一个lua/get,用来获取nginx现有的配置。

1. 提供mock跳转配置设置/获取接口。

示例

代码语言:javascript
复制
 curl 'http://proxy.**.com/lua/pour?project=test&group=mock&ttl=' -H "Cookie: auth=lua" -d 'value={"user/1**":{"4--60":true,"4--61":true}}'

 curl 'http://proxy.**.com/lua/get?project=test&group=mock'
参数

group: 写死为mock,表示mock配置

project: 项目名称,比如live、test等

ttl: 这个配置的过期时间,默认是3600秒

value: 配置信息,是一个json串,详见以下说明

对于配置value的说明

示例

代码语言:javascript
复制
{
    "user/1**" : {
        "4--60" : true,
        "4--61" : "4.4.4.4"
    },
    "user/2**" : {
        "*" : true,
        "4--60" : "4.4.4.4"
    },
    "*" : {
        "*" : "8.8.8.8",
        "4--67" : true,
    }
}

说明: json数组的第一级是url,注意这个url不带前导/,第二级是uid,匹配客户端请求参数中的userid;uid对应的值为mock地址,如果值为true,则转到默认的...(mock服务器) 这两级都可以配置为通配符*,匹配的优先级为先匹配精确的,再匹配通配符 例如上面这个例子中,如果4--61这个用户访问user/1**接口,则会转到4.4.4.4,而4--88这个用户访问的话,会被指到8.8.8.8

2. 根据配置跳转业务请求到mock服务

代码语言:javascript
复制
-- 转到对应的机器
local proxy_res = cache:get(project .. "_proxy")
if proxy_res and proxy_res ~= "" and (ngx.req.get_headers()["x-proxy-host"] == nil or ngx.req.get_headers()["x-proxy-host"] == "") then
    -- 增加错误处理,对于有问题的json啥的,做容错
    local status, proxy_cnf = pcall(function(proxy_res) 
        local cjson  = require "cjson"
        return cjson.decode(proxy_res)
    end
    , proxy_res)
    if status == false then
        proxy_cnf = nil
    end

    if proxy_cnf and type(proxy_cnf) == "table" then
        if proxy_cnf[ngx.var.arg_userid] then
            ngx.req.set_header("x-proxy-host", proxy_cnf[ngx.var.arg_userid])
            ngx.exec("@proxy")
        elseif proxy_cnf[ngx.var.arg_deviceid] then
            ngx.req.set_header("x-proxy-host", proxy_cnf[ngx.var.arg_deviceid])
            ngx.exec("@proxy")
        end
    end
end
使用方法

最后的最后,一切准备就绪,使用就非常简单了

使用方式一的步骤(如图):

1. 新增要mock接口的uri对应的返回数据

2. Mock后台新增跳转配置,如配置user/1**, uid=4--86跳转

2. 手机/前端正常操做请求,即可返回定制数据

mock

使用方式二的步骤:

1. wifi或本机hosts绑定请求接口域名到mock服务器 1.1.1.1 passport.**.com

2. 手机/前端连接绑host的wifi,返回定制数据

 整个方案的过程中,我们也是一直在摸索调整,如:一开始的时候我们也并没有针对用户来做mock数据的区分,使用时碰到开发有多人同时使用的情况,一个人改了数据,另外一个人使用时发现不对了;还有https证书的问题,花椒没有提供moco框架https服务需要的证书,为了Mock服务能同时支持客户端直接绑host的方式,采用ngnix跳转服务的方式,先处理完证书验证,再跳转到mock服务。目前我们的mock服务偏向于给开发人员和手工测试人员提供便捷的模拟服务,mock在自动化测试上的应用还未被完全挖掘出来,有待进一步探讨。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-08-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端自习课 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是Mock?
  • 接口Mock用处?
  • 花椒的Mock方案
    • * Mock后台
      • * Mock Service
        • * 业务服务器跳转处理
          • 使用方法
          相关产品与服务
          数据库
          云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档