全系统接口一键mock实践

2,002 阅读7分钟

题目有点大,下面简单说下要解决的问题以及对应的解决方案思路。

问题

mock也是前端工程化的一部分,所以正常来讲每个前端项目都会有各自mock 的实现。

一般前端实现mock,有不限于以下几种形式:

  • 手写假数据,接口请求直接返回写好的假数据;
  • mock.js拦截接口,并返回对应编写好的mock;
  • easymock、yapi等平台接管;
  • Json-server拦截+faker生成mock;
  • ......

以上方式各有优缺点,场景不同,需求也不一样,存在即合理,不必强分好坏。

但根据个人调研使用,无论使用哪一种,都免不了诸如以下:

  • 接口、参数的复制粘贴
  • mock数据大多只支持查询

等通用性问题,当然也可能是因为使用不够深入的原因。所以基于这些问题,就想着能不能把这种通用性问题通过工具去解决呢?

所以就有了本篇内容的实践。

实现步骤

大概捋一下思路:

  1. swagger-json生成接口、配置信息;
  2. json-server接管并处理对应请求;
  3. faker根据1的接口配置信息,处理mock数据;
  4. 整合23步骤,校验mock的增删改查功能;
  5. 客户端校验;

看步骤可知,和通常mock方式不一的,核心是多了第一个步骤,动态生成全系统接口及相关出入参配置信息,以及多种方式的整合处理。

过程工作量会比较大,实现过程也不一定相同,但原理是一样的,所以本篇内容偏理论,下面仅讨论实现原理。

1. 接口配置

实现接口mock的过程,通常这部分工作的重复量是最大的,就是手动的复制接口及出入参,然后针对的处理mock。

所以基于这种情况,之前实现了通过类似swagger等平台,一键获取接口及出入参配置的功能。

可看 swagger-json 通过swagger接口快速生成AntDesign组件配置

简单讲下swagger-json的实现原理:

  1. 根据后端提供的swagger-ui地址,获取渲染swagger-ui的接口;
  2. node环境请求接口,解析对应的接口及出入参数据结构;
  3. 按需组装出入参,生成对应需要的出入参配置;
  4. 生成对应json文件,方便一键取用,大量减少一个个复制粘贴的工作;

实现过程的重点是swagger接口的数据解析,以及按需数据的组装,剩下的就是文件的读写。

实现之后基本随处可用,根据不同需求,改改出入口模型就行,收益比例比较高。

贴一个生成的简单例子

/** 
	接口:get-people-list 
	生成文件:get-people-list.json
	生成配置如下:
	*/
{
    "query": [
        {
            "key": "name",
            "label": "查询人",
            "children": []
        },
        {
            "key": "age",
            "label": "查询年龄",
            "children": []
        },
        {
            "key": "tel",
            "label": "查询电话",
            "children": []
        }
    ],
    "params": [
        {
            "key": "name",
            "label": "姓名",
            "children": []
        },
        {
            "key": "age",
            "label": "年龄",
            "children": []
        }
    ]
}

根据上面的json,可以很方便的接入如Antd的表单及table等组件的config部分,省去手动配置的过程。

2. 请求接管

上面生成了对应的接口及配置,接下来处理请求接管的部分。

mock.js等也可以接管请求,但使用json-server更好的地方,在于json-server实现并增强了dbserver的处理,基本达到仿真db的能力。

下面是处理过程:

  1. 根据json-server读写规则,同步、修改上面生成的接口及配置;

    根据接口的特性,请求路径及req、res等一般都需要做rewrite才能满足需求,而json-server的匹配规则个人感觉有点绕且不是很清晰。

    但这部分是请求接管的核心,不能省略。

    因为是一次性处理整个对接系统的接口,所以接口越多工作量和复杂度相对也越大一些。

    贴个简单的rewriter例子:

    {
        //重写 /app/路径
        "/app/*": "/",
        // post请求接口 /get/list/1,json-server实际会对文件get-list.json发起get-list且id为1的请求,最终返回id=1的数据
        "POST/get/:people/:id": "GET/app-:people/:id",
    }
    

    规则比较简单,所以也只满足了基本需求。

  2. 启动server,接口调试;

    参考上面的接入,可以拿几个简单的接口,做下匹配及转译,然后启动server,先做查询、新增的调试,成功之后实现批量操作。

    参考 simple-example

  3. 整合接口list,json监听;

    单个接口调试完成了增删改查流程,基本规则也就摸的差不多清楚,接下来整合接口。

    需要整合的原因是当json文件过多的时候,json-server监听无法达到预期,原因也没有深究,所以干脆做了整合,只监听一个文件。

    这个时候如果想调试大量的接口,就需要不停复制粘贴相关接口及出入参,效率极其低下,这时候就体现了上面swagger-json实现的好处了。

    下面简单看下实现后的贴图

image.png
  1. 按需调试,磨平差异

    接口量大,不一定每个接口的情况都能兼顾到,这个时候需要根据不同情况,做不同的接口rewrite及req、res的拦截转换处理。

    其实如果后端接口实现足够规范,前面1~3基本能满足需求,但事实总是不能如人意,所以这步往往没法省略。

    json-server也考虑到这点,提供了不同情况的处理,下面是部分规则截图

    image.png
  2. 拓展处理

    假设json-server仍然无法满足对拦截处理的需求,可以考虑手动接入更符合日常使用的express等作拓展处理。

3. faker数据

前面调通了json-server的拦截,简单实现了接口对应的增删改查功能,但对查询而言,往往需要大量数据的mock。

对大量数据的生成,这里用的是faker-js+lodash实现。

原理就是lodash负责化量,faker负责生成

下面贴个简单demo:

import { faker } from "@faker-js/faker"
import { times } from "lodash-es"

// db数据faker
export function fakerDb (params /** 出参 */ = {}, length/** mock数据长度 */ = 20) {
  const mock = times(length, function (n) {
    const obj = {}
    const keys = Object.keys(params)
    for (const key of keys) {
      obj[key] = faker.name.fullName()
    }
    return {
      ...obj,
      id: n + 1
    }
  })

  return mock
}

再结合上面的接口接管及整合,就能够生成仿真mock。

下面看下整合后每个接口faker20条数据的mock情况

image.png

4. 客户端校验

上面其实已经基本实现了mock平台的功能,接下来就是在dev等环境实现接口的真实mock。

和常规流程一样:

  1. 启动上面mock-server,比如启动后地址是localhost:3000;
  2. 真实请求把proxybaseUrl换成mock的地址及对应配置;
  3. 发起请求;

下面看下真实环境的演示过程:

  1. 发起请求

    // Get默认是查询功能,Post是新增
    axios.get("http://localhost:3000/app/matter/detail").then(res => {
      console.log('Mock:', res);
    })
    axios.post("http://localhost:3000/app/matter/detail").then(res => {
      console.log('Mock:', res);
    })
    
  2. 控制台验证

    image.png
  3. mock文件验证

    image.png

    可以看到chrome控制台及本地接口整合并接入faker后的mock/index.json都生成了对应数据,这也是使用faker替代mockjs的原因,可以更真实的反馈fake-db情况。

总结

上面只是讲了实现的基本原理及过程,具体实现过程的工作量还是相对大一些,也就不再细述,下面再次总结下过程:

  1. 通过swagger接口获取组装并生成接口配置的json文件;
  2. json-server拦截请求做转发处理;
  3. faker生成db数据;
  4. 发起proxy请求验证;

还是上面的话,前端mock有多种多样的实现方案,这里也只是针对自身情况,对已有的功能做整合,但不管如何实现,需求其实都是一致的。

这个最终的需求就是赋能增效,这也是程序员工作本身永恒的主旋律,只要能更好的实现需求,方法本身也只是某个阶段的某个恰好的方法而已。

所以程序员实现需求只是基本要求,能够更好的、创新性的实现,才是推动技术发展的重要能力。