搭建一个低配版的Mock Server
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
使用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的更多相关文章
- 【Node/JavaScript】论一个低配版Web实时通信库是如何实现的( WebSocket篇)
引论 simple-socket是我写的一个"低配版"的Web实时通信工具(相对于Socket.io),在参考了相关源码和资料的基础上,实现了前后端实时互通的基本功能 选用了Web ...
- 【Java】利用注解和反射实现一个"低配版"的依赖注入
在Spring中,我们可以通过 @Autowired注解的方式为一个方法中注入参数,那么这种方法背后到底发生了什么呢,这篇文章将讲述如何用Java的注解和反射实现一个“低配版”的依赖注入. 下面是我们 ...
- 【JavaScript】论一个低配版Web实时通信库是如何实现的之二( EventSource篇)
前情提要 「 话说上回说到!那WebSocket大侠,巧借http之内力,破了敌阵的双工鸳鸯锁,终于突出重围. 然而玄难未了,此时web森林中飞出一只银头红缨枪,划破夜色. "莫非!?&qu ...
- 基于canvas和web audio实现低配版MikuTap
导言 最近发掘了一个特别happy的网页小游戏--MikuTap.打开之后沉迷了一下午,导致开发工作没做完差点就要删库跑路了,还好boss瞥了我一眼就没下文了.于是第二天我就继续沉迷,随着一阵抽搐,这 ...
- 搭建react项目(低配版)
react项目低配版,可作为react相关测试的基础环境,方便快速进行测试. git clone git@github.com:whosMeya/simple-react-app.git git ch ...
- Jenkins 结合 Docker 为 .NET Core 项目实现低配版的 CI&CD
随着项目的不断增多,最开始单体项目手动执行 docker build 命令,手动发布项目就不再适用了.一两个项目可能还吃得消,10 多个项目每天让你构建一次还是够呛.即便你的项目少,每次花费在发布上面 ...
- unittest框架(惨不忍睹低配版)
根据我上个随笔的unittest框架优化得来,虽然对于smtp模块还是有点迷糊,不过还是勉强搭建运行成功了,还是先上代码: #login_test.py import requests class L ...
- 分享一个低配VPS下运行的mysql配置文件
在各种内存CPU核心只有1/2核,内存只有512M/1G的vps下,内存.CPU.硬盘都不是太充裕.因此主要思路是,禁止吃内存大户innodb引擎,默认使用MyISAM.禁止吃硬盘大户log-bin, ...
- java线程学习第一天__低配版的卖面包机
package Thread;import javax.xml.bind.ValidationEvent;class snacks{ private int SaledSnacks=0; ...
随机推荐
- 07-NABCD项目分析
时 间:2020.3.31 参加人员:向瑜.赵常恒.刘志霄 讨论记录内容: NABCD模型 ·N(need)-向瑜 你的创意解决了用户的什么需求? 1. 随时随地记录个人收支的明细,清楚明白的知 ...
- Java基础高级篇 NIO
nio模型与io模型的对比 netty 是什么 怎么使用
- Dubbo系列之 (一)SPI扩展
一.基础铺垫 1.@SPI .@Activate. @Adaptive a.对于 @SPI,Dubbo默认的特性扩展接口,都必须打上这个@SPI,标识这是个Dubbo扩展点.如果自己需要新增dubbo ...
- java 字符串缓冲区与正则表达式
一 字符串缓冲区 1.StringBuffer类 查阅StringBuffer的API,StringBuffer又称为可变字符序列,它是一个类似于 String 的字符串缓冲区,通过某些方法调用可以改 ...
- 使用halo搭建自己的博客并配置https域名访问
首先进行java配置 # 1. 下载jdk [下载地址](https://www.oracle.com/cn/java/technologies/javase-downloads.html) - 一定 ...
- SpringMVC常见问题Error configuring application listener of class org.springframework.web.context.ContextLoaderListenejava.lang.ClassNotFoundException: org.springframework.web.context.ContextLoaderListener
六月 20, 2018 9:43:34 下午 org.apache.catalina.core.StandardContext listenerStart 严重: Error configuring ...
- unity探索者之微信分享所有流程,非第三方插件
版权声明:本文为原创文章,转载请声明http://www.cnblogs.com/unityExplorer/p/7560575.html 很久没有写新博客了,前段时间有些忙,这几天趟了几个微信分享的 ...
- 大整数加法C++(计蒜客)
求两个不超过 200200 位的非负整数的和. 输入格式 有两行,每行是一个不超过 200200 位的非负整数,可能有多余的前导 00. 输出格式 一行,即相加后的结果.结果里不能有多余的前导 00, ...
- 笔记:Linux用户管理(补充)、权限管理、内存管理、网络管理、渗透常用命令
一.用户管理(补充) 添加用户:useradd [选项] 用户名 useradd -u 5000 -g demogroup -G root -d /home/demo -s /bin/bash dem ...
- composer安装包的时候触发PHP fatal error,提示允许的内存耗光
在composer require之前加COMPOSER_MEMORY_LIMIT=-1