mock翻译过来是模仿的意思,Server是服务器。粗暴点直译就是模仿服务器。

写在前面

通过阅读本文,你将对Mock的使用有一定的了解,对前后端分离的概念有了更深一步的认识,对Koa的使用有一定的了解。本文先从背景出发去抛出“我们为什么要用Mock?”的灵魂拷问,紧接着我们通过Mock在前后端的使用来进行实战落地,最后我们再总结回顾,展望高配版的Mock Server。

本文不会像念经一样把官方文档的API抄一遍告诉读者这个怎么用,那个怎么用,更多地是提供一个思路或者想法以及项目的落地带着大家学习Mock的使用。因为我坚信“官方文档始终是最权威的文档。”,所以“Do Not Repeat"原则,不要做念经这种事情,因为官方文档写的已经很详细了。还有就是有些项目API茫茫多,如果都全面地写一遍,累死啦,这个是官方文档干的事情。技术只有转换成生产力,才是程序员的赚钱的核心竞争力,劝君莫惜金缕衣,劝君惜取少年时。

这里简单地罗列下Mock的整体知识,读者后续可以根据这个大纲有选择地去看。

API

  • Mock.mock()
  • Mock.setup()
  • Mock.random()
  • Mock.valid()
  • Mock.toJSONSchema()

据不完全统计,Mock支持18种数据定义,172种数据定义写法。具体的参见:http://mockjs.com/examples.html

参见:https://github.com/ataola/node-blacksmith/blob/master/code/framework/koa-study/koa-mock/mock/random/basic.js

使用Mock的背景

我们为什么要使用Mock?

传统的非前后端分离的项目,后端老哥除了要做对接服务器数据库相关的工作,还要搞前端页面,太多太累太杂了。随着时代的发展、人类社会的进步,编程技术的更新迭代,慢慢地开始有了专职的前端程序员和后端程序员等等,项目越来越复杂,前后端的要求度逐步提高,尤其是Node.JS技术的迅猛发展,十一年弹指一挥间,在npm、github各类库和项目如雨后春笋般蹭蹭蹭地雄起,给开发者提供了很多解决方案,这也使得前后端分离成为可能。事物存在的即是合理的,但我们也要辩证地去看待这个事物。前后端分离项目的落地比前后端不分离的落地增加了开发人员对接沟通的成本,在某些场景下,前端开发会受限制于后端开发,接地气地说就是后端接口没写好没提供前端可能就无从下手了,为了解决这个问题,我们需要进行相关地Mock,来模拟后端返回的数据也好或者后端的接口也好,总之,我们需要一个Mock Server。

Mock在前端的使用

安装

# npm安装
npm i mockjs -D

引入方式

传统script脚本引入

去Bootcdn引入相关的脚本,地址:https://www.bootcdn.cn/Mock.js/, 形如

<!-- 生产环境 -->
<script src="https://cdn.bootcdn.net/ajax/libs/Mock.js/0.1.1/mock-min.js"></script>
<!-- 开发环境 -->
<script src="https://cdn.bootcdn.net/ajax/libs/Mock.js/0.1.1/mock.js"></script>

ES Module

import Mock from 'mockjs';

CommonJS

const Mock = require('mockjs');

Mock.mock( rurl?, rtype?, template|function( options ) )使用

  • rurl: 当拦截到匹配 rurl 的 Ajax 请求时,将根据数据模板 template 生成模拟数据,并作为响应数据返回
  • rtype:当拦截到匹配rtype 的 Ajax 请求时,将根据数据模板 template 生成模拟数据,并作为响应数据返回。
  • template:生成模拟数据的模板
  • function: 当拦截到匹配 rurl 的 Ajax 请求时,函数 function(options) 将被执行,并把执行结果作为响应数据返回。

具体的参见:https://github.com/ataola/node-blacksmith/tree/master/code/framework/koa-study/koa-mock/static

Mock在后端的使用

在前面我们了解了Mock在前端的使用,我们还需要思考这么一个问题,模拟也要模拟的深沉一点,也就是像一点,前面的写法足以应付大部分场景,但是有的时候我们需要拟合后端的服务,比如网络的延迟、跨域、性能等等问题,我们更加期望是搞一个服务器,模拟后端的一些API行为。作为前端选手,Javascript天然会,既然用了Javascript的基础,我们自然而然地会想到用Node.JS去搭建一个后端服务。

笔者这里使用Koa搭建一个后端服务,主体代码如下:

const http = require('http');

const Koa = require('koa');
const app = new Koa();
const logger = require('koa-logger');
const bodyparser = require('koa-bodyparser')
const onerror = require('koa-onerror');
const errorMiddleware = require('./middlewares/error');
const ipBlackListMiddleware = require('./middlewares/ip_blacklist');
const { host, port, ip_blacklist } = require('./config/index'); // import routes
const IndexRoute = require('./routes/index');
const MockRoute = require('./routes/mock'); // error handler
onerror(app); app.use(ipBlackListMiddleware(ip_blacklist)); // when post, use x-www-form-urlencoded or json
app.use(bodyparser({
enableTypes:['json', 'form', 'text']
})); // use koa-logger
app.use(logger()); // routes middleware
app.use(IndexRoute.routes(), IndexRoute.allowedMethods());
app.use(MockRoute.routes(), MockRoute.allowedMethods()); // error-handling
app.on('error', errorMiddleware()); // create a server
const server = http.createServer(app.callback()); // listen port
server.listen(port, host, () => {
console.log(`mock server is running in http://${host}:${port}`);
}); module.exports = server;

大致的一个流程是,导入了项目的npm包,中间件、路由,初始化Koa实例,调用了相关的中间件和路由,最后监听服务器端口。

如果对Mock不是很熟,我们大致会这样做,把相关返回信息写在JSON文件中或者js文件中,然后通过引入或者读取相关文件来做这件事

JSON文件形式

{
"data": {
"name": "zjt",
"age": 23
},
"success": true,
"code": 1,
"message": "获取用户信息成功"
}

定义完返回格式后,我们可以通过commonJS的语法用require引入,也可以通过内置的fs模块的读取文件的函数去读取这部分JSON的内容,然后把它衔接到相关路由上面构成一个Mock API。

形如:

const user_json = require('../mock/json/user.json');

router.get('/json/user', async ctx => {
ctx.body = user_json;
});

JS文件形式

这里仿照楼上也是类似的。

const user_js = require('../mock/js/user');

router.get('/js/user', async ctx => {
ctx.body = user_js;
});

这样做的话,能够满足我们日常生活中的大部分开发,但是太费劲了,每次我们都要写这么多一坨坨的JSON或者JS文件,我们希望这个Mock Server能够更加智能一点,本着”简单、短小精悍“的原则去思考,我们自然而然会想到引入Mock.JS去做这件事情。

Mock.JS的应用

这里我们思考一个例子,最常见的就以返回用户身份信息为例。我们就意思下,罗列一下用户常见的属性,比如说用户id、用户名字、用户昵称、用户生日、用户地址、用户邮箱、能量值(也可以理解成阳光值)、创建时间、更新时间

const Mock = require('mockjs');

const data = Mock.mock({
'data|4-10': [{
'id': '@id',
'name': '@cname',
'nickname|1': ['沉鱼', '落雁', '闭月', '羞花'],
'birthday': '@date',
'address': '@county(true)',
'email': '@email',
'power|1-5': '★',
'created': '@now',
'updated': '@now'
}]
}); module.exports = {
data,
success: true,
code: 1,
message: '获取用户数据成功'
};

简单的讲下

  • 'data|4-10'[{}]: 表示有个数组data,它里面至少有4个对象,上限10个对象
  • @id: 表示数据占位符定义,一个id
  • @name: 表示数据占位符定义,一个name
  • 'nickname|1': ['沉鱼', '落雁', '闭月', '羞花'],: 表示nickname为一个字符串,值为沉鱼落雁闭月羞花中的一个。
  • @date: 表示数据占位符定义,一个形如1997-06-13这样的日期
  • @county(true): 表示数据占位符定义, 一个形如江苏省 淮安市 金湖县这样的地址
  • @email: 表示数据占位符定义,一个邮箱
  • 'power|1-5': '★': 表示有个字符串,值为最少1颗星,最多5颗星,其实这个做外卖五分好评或者老师课程评价这种数据展示应景一些
  • @now: 表示当前时间。

最后的效果就是

这里我们可以看出Mock的结果还是有些不可控性,比如我就想让它显示正常点的邮箱、可读性强一点的段落文字,这里就要用到文中的沉鱼落雁闭月羞花的例子,我们事先准备好部分结果集让其Mock数据。

Mock数据的单元测试

这里我是结合Mocha(测试框架)、chai(断言)、supertest(模拟http测试)对Mock的API进行了一个单元测试,具体的如下:

const app = require('../server');
const supertest = require('supertest')(app);
const expect = require('chai').expect; describe('mock Server', () => {
describe('#GET /', () => {
it('should return a response with HTTP code 200', function(done) {
supertest
.get('/')
.expect(200, done);
});
}); describe('#GET /mock/js/user', () => {
it('response data success should return true', (done) => {
supertest
.get('/mock/js/user')
.expect(200)
.end((err, res) => {
if (err) {
done(err);
}
const { code, data, message, success } = res.body;
expect(res.statusCode).to.equal(200);
expect(res.body).to.be.an('object');
expect(code).to.eql(1);
expect(data).to.eql({ name: 'ataola', skill: 'node.js' });
expect(message).to.eql('获取用户信息成功');
expect(success).to.eql(true);
done();
});
});
});
});

高配版的Mock Server

站在产品经理的角度,我想,高配版的Mock Server就是打开浏览器,有个界面给你点点点进行增删改查,然后生成一个API,有兴趣的童鞋可以去实现下,溜了溜了。。。

最后

本文选自“Node.JS打铁”系列文章,项目地址:https://github.com/ataola/node-blacksmith

文中涉及到的项目例子地址:https://github.com/ataola/node-blacksmith/tree/master/code/framework/koa-study/koa-mock

参考文献

Mock.JS官网: http://mockjs.com/

MockJS 文档:https://github.com/nuysoft/Mock/wiki

MockJS 示例:http://mockjs.com/examples.html

MockJS语法规范:https://github.com/nuysoft/Mock/wiki/Syntax-Specification

Mock.Mock()的使用:https://github.com/nuysoft/Mock/wiki/Mock.mock()

搭建一个低配版的Mock Server的更多相关文章

  1. 【Node/JavaScript】论一个低配版Web实时通信库是如何实现的( WebSocket篇)

    引论 simple-socket是我写的一个"低配版"的Web实时通信工具(相对于Socket.io),在参考了相关源码和资料的基础上,实现了前后端实时互通的基本功能 选用了Web ...

  2. 【Java】利用注解和反射实现一个"低配版"的依赖注入

    在Spring中,我们可以通过 @Autowired注解的方式为一个方法中注入参数,那么这种方法背后到底发生了什么呢,这篇文章将讲述如何用Java的注解和反射实现一个“低配版”的依赖注入. 下面是我们 ...

  3. 【JavaScript】论一个低配版Web实时通信库是如何实现的之二( EventSource篇)

    前情提要 「 话说上回说到!那WebSocket大侠,巧借http之内力,破了敌阵的双工鸳鸯锁,终于突出重围. 然而玄难未了,此时web森林中飞出一只银头红缨枪,划破夜色. "莫非!?&qu ...

  4. 基于canvas和web audio实现低配版MikuTap

    导言 最近发掘了一个特别happy的网页小游戏--MikuTap.打开之后沉迷了一下午,导致开发工作没做完差点就要删库跑路了,还好boss瞥了我一眼就没下文了.于是第二天我就继续沉迷,随着一阵抽搐,这 ...

  5. 搭建react项目(低配版)

    react项目低配版,可作为react相关测试的基础环境,方便快速进行测试. git clone git@github.com:whosMeya/simple-react-app.git git ch ...

  6. Jenkins 结合 Docker 为 .NET Core 项目实现低配版的 CI&CD

    随着项目的不断增多,最开始单体项目手动执行 docker build 命令,手动发布项目就不再适用了.一两个项目可能还吃得消,10 多个项目每天让你构建一次还是够呛.即便你的项目少,每次花费在发布上面 ...

  7. unittest框架(惨不忍睹低配版)

    根据我上个随笔的unittest框架优化得来,虽然对于smtp模块还是有点迷糊,不过还是勉强搭建运行成功了,还是先上代码: #login_test.py import requests class L ...

  8. 分享一个低配VPS下运行的mysql配置文件

    在各种内存CPU核心只有1/2核,内存只有512M/1G的vps下,内存.CPU.硬盘都不是太充裕.因此主要思路是,禁止吃内存大户innodb引擎,默认使用MyISAM.禁止吃硬盘大户log-bin, ...

  9. java线程学习第一天__低配版的卖面包机

    package Thread;import javax.xml.bind.ValidationEvent;class snacks{    private int  SaledSnacks=0;   ...

随机推荐

  1. 如何利用Python在网上接单,兼职也能月薪过万

  2. 数电学习笔记之CMOS传输门工作原理

    CMOS 传输门从结构上看是由一个PMOS和一个NMOS管组成 先简单粗略讲讲PMOS管和NMOS管导通与截止吧 首先我们MOS管有三个极,源极(S:Source).漏极(D:Drain)和栅极(G: ...

  3. JS 导航条切换案例

    HTML代码: <div class="tab"> <div class="tab_list"> <ul> <li c ...

  4. wordpress-技术博客主题推荐

    推荐主题 1.WordStar 这个主题是干净的,以博客为中心,设计清晰,简单,直接的排版,可在各种各样的屏幕尺寸可读,适合多种语言. 效果图 还是非常简洁, 基本和CSDN差不多了 除了没有广告以外 ...

  5. 02树莓派4B—C语言编程——PWM

    01树莓派直接输出PWM波 —— 硬件PWM程序  (推荐使用) #include <stdio.h> #include <wiringPi.h> #include <s ...

  6. 运用sklearn进行主成分分析(PCA)代码实现

    基于sklearn的主成分分析代码实现 一.前言及回顾 二.sklearn的PCA类介绍 三.分类结果区域可视化函数 四.10行代码完成葡萄酒数据集分类 五.完整代码 六.总结 基于sklearn的主 ...

  7. Revit二次开发——非模态窗口的事件处理

    一.起因    自己在写revit二开时,有一个Winform窗体按钮点击事件需要 触发调用事务进行处理,结果出现“异常“Starting a transaction from an external ...

  8. 题解 P1407

    建图方式:旧关系女人连男人,现关系男人连女人(当然,反过来也可以) 原因可以这样考虑: 如果一个男的把女的绿了,那么这个女人就会去找一个她曾经交往过的男人,也就是在这种情况下,某种"影响&q ...

  9. Python-Opencv 轮廓常用操作

    Python-Opencv 轮廓常用操作 1.颜色空间转换 使用cv2.cvtColor(input_image ,flag),flag为转换类型 常用的转换类型有: BGR和灰度图的转换使用 cv2 ...

  10. Spring @Transactional事物配置无效原因

    spring @transaction不起作用,Spring事物注意事项 1. 在需要事务管理的地方加@Transactional 注解.@Transactional 注解可以被应用于接口定义和接口方 ...