新手区 菜鸟搭建 Mock 服务器实践:Anyproxy+Moco

terrychow · 2016年09月21日 · 最后由 hellolixianghua 回复于 2018年09月12日 · 5083 次阅读
本帖已被设为精华帖!

一、前言

  • 这次分享主要和mock相关的,mock测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法,尤其是如果项目需要第三方的数据,但第三方由于权限等问题又不能直接提供对应的数据,造成测试范围覆盖不全的情况,在这种情况下就可以用mock来代替第三方的数据以欺骗客户端响应,达到对应的测试效果。
  • 最近没怎么写帖子了,工作比以前忙,但还是会抽空学学新知识的,之前一直想自己学一下写一个mock服务器,但技术和时间的限制,一直都做不起来,直到有一天突然发现了moco.jar,又直到某一天突然发现了Anyproxy,又直到某一天突然脑袋一闪,结合了两者的长处互补,最后就做起来了一个简单Mock服务器了,大概的过程如下:

好吧,切入正题


二、工具介绍

1、Anproxy:http://anyproxy.io/cn/
AnyProxy 是一个基于 Node.js 的代理服务器。代理服务器是个中间人,站在了客户端和服务端中间,双方通信的每个比特,都会滴水不漏地经过它。它控制了完整的请求头、请求体、响应头、响应体,可以在客 户端与服务端都无感知的情况下介入处理所有的流程。只要代理服务器可以实现灵活配置,前端工程师们的奇葩需求就有出头之日了。

特点:

  • 支持 https 明文代理
  • 支持低网速模拟
  • 支持二次开发,可以用 javascript 控制代理的全部流程,搭建前端个性化调试环境
  • 提供web版界面,观测请求情况

尤其是第3点,由于可以控制代理,所以就可以控制请求和响应的数据,其实就Anproxy本身就可以mock了,但存在一个问题,每次修改Mock数据之后都必须重启Anproxy,一旦重启Anyproxy,连接的客户端就会断开一次网络,这样对于即时通讯需要保持频繁心跳的产品来说是一个比较致命的打击,所以既不能重启Anproxy,又想随时改变Mock数据,那怎么做了,这里就可以用Moco了


2、Moco:http://blog.csdn.net/sanjay_f/article/details/50204883

  • Moco其实就是MockServer的一个实现。在日常的开发及测试过程中,我们不难发现不同模块之间的测试、协作和集成有时候是一件很困难的事情,往往因为某个模块开发进度落下了,或是某个模块没有配置正确,使得其他模块的测试和开发进度受到限制。通常这被称为短板效应。 由于负责的模块依赖其他底层模块,在进行性能测试时必须先将其他底层模块全部部署调试通顺,才能进行下一阶段的性能作业。而其他模块如若尚未开发完毕,亦或开发完较难搭建,在部署调试过程中往往就会花费大量时间和精力,具体的使用方法点链接看就可以啦

Moco启动很简单


而且Mock数据被修改的话会自动刷新


但是Moco有个问题,Moco启动的是一个服务器,意思是如果要Mock的话,所有的请求都得在Moco启动的服务器中处理,但是如果想保留原有的未mock的接口的正常使用的话那就做不到了,可能说的不太清楚,举个例子:

  • 原服务器地址为www.test.com,Moco启动的地址为本地127.0.0.1,现在要mock一个名为test01的接口,但要保持test02,test03等接口的正常使用,好了,如果直接使用MOCO的话,意思是所有的接口都要求被Mock,因为127.0.0.1中是没有test02、test03等接口的,但又要保持其能正常使用,然后哪有那么多工作量去把所有接口的mock都写起来,如果都写起来了,还不如直接写一个服务器算了,而且也难维护,所以结合两者的特点,刚好互补,就可以用来搭建一个简单实用的Mock服务器了

3、搭建过程

首先还是像上图一样启动Moco先了,然后测试一下是否返回的数据是准确的

然后就可以编写Anproxy的控制代理的规则了,像流程图中的一样逻辑,如果客户端请求的是被Mock接口,就会去本地的MOCO中取Mock的响应数据返回给客户端,如果不是,那就直接回到原服务器就好了,这里是用了Anyproxy的rule_use_local_data.js来控制让客户端在使用被mock接口时Anyproxy指向mock服务器,自己也可以把js脚本名称改一下,便于知道是干嘛用的,如我改成了rule_mock.js,个人爱好,不改也可以

具体的实现代码:

rule_mock.js
module.exports = {

summary:function(){
return "replace response data by local response now";
},

//mark if use local response
shouldUseLocalResponse : function(req,reqBody){
if(/checkVersionAndLogin/.test(req.url)){ //被mock接口判断选择
req.replaceLocalFile = 0;
return true;
}

if(/reply/.test(req.url)){
req.replaceLocalFile = 1;
return true;
}

return false;
},

dealLocalResponse : function(req,reqBody,callback){
if(req.replaceLocalFile==0){
request = require('request-json');
var client = request.createClient('http://127.0.0.1');
client.get('/checkVersionAndLogin', function(err, res, body) //触发mock,到moco中获取mock响应数据
{
console.log('the resp is ------------------------->',res.statusCode,res.headers,body);
var newDataStr=JSON.stringify(body);
callback(res.statusCode,res.headers,newDataStr); //mock数据返回给客户端
}
);
}
}
};

然后就可以启动Anyproxy,默认是8001端口,-i 表示支持https,具体使用看上面的链接吧


然后如果在浏览器中使用的话去设置代理就好了,如果是移动设置使用的话,连接在对应启动服务器的笔记本电脑中wifi,在wifi中设置对应的代理即可,和fiddler设置代理的操作是一样的

其实就这样,Mock服务器就搭建完成了

四、Mock过程

模拟输入正常的用户和密码后登录后返回自定义字段使登录异常
这个只是个例子,可能mock这个没有什么意义,但还是先试一试,使用的mock数据为


在测试的客户端输入正确的用户名和密码后点击登录按钮后,登录失败,查看返回的数据


其实大概的过程就是这样,当判断到客户端使用的接口为设定的接口的话,Anyproxy就会触发代理控制,作为一个选择mock接口的中间工具,去请求moco中的数据返回给客户端,这样就能起到对特定接口进行mock而不影响其他未mock接口的正常使用的效果

5、其他

其实应该有人会觉得没必要用moco来做mock数据,用个excel之类的保存数据然后每次读取就好了,其实我的想法是如果读出来的数据又要自己把它们组装成请求,然后再转发回客户端,显然有点麻烦,还不如直接用moco返回个response对象给客户端去处理了,这个反而会更方便,好吧,就写到这里了,看看各路大神有什么建议可以让我改进一下的,毕竟这种mock还是比较简陋的,继续欢迎大家吐槽

如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 30 条回复 时间 点赞
Monkey 将本帖设为了精华贴 09月21日 09:57

加精理由:图文并茂,流程清晰,以资鼓励。

不过,代码要修改下,不要都用图。代码要用markdown

这个可以

谢谢分享,一直想研究下这方面的知识

#2楼 @monkey 好的,等下改改,谢谢鼓励

—— 来自TesterHome官方 安卓客户端

6楼 已删除

需要npm install request-json

#7楼 @jaychang1989 是的,用于去moco拿请求

—— 来自TesterHome官方 安卓客户端

不错,有图有文,值得学习

—— 来自TesterHome官方 安卓客户端

加精理由: mock服务的正确做法

简单易用,图文并茂,有准备动手试一下!

大赞~ 麻溜的去部署一套环境去了

moco有时候对中文支持不是很方便 ,不过Anyproxy真心超级好用,超级赞~~ 大家快去试用吧😁 😁

#13楼 @xushizhao 中文这个的确得考虑一下,感觉用AnyProxy是可以处理的

—— 来自TesterHome官方 安卓客户端

Fiddler自定义规则也可以实现mock的功能,一直想知道是否有可以mock接口内部调用的方法呢

—— 来自TesterHome官方 安卓客户端

anyproxy之前想研究一下,有时间争取看一下里面的代码。
我这里自己写了一套,不过node只是做为代理服务器,生成Mock的逻辑都在spring里面。
Node做代理拦截除了拦截请求,还要对其他请求做二次转发。
自己写的时候app->fiddler->node代理经常504,后来有一个workaround。
http、和https基本上来说ok。
目前还在尝试解决http2.0,如果anyproxy支持,值得研究一下。

Best Regards,
Lucas Luo

#16楼 @lucasluo 用anyproxy的确省事,主要是好上手好理解,当初研究anyproxy也要一定时间,我后面也会做一些协议等兼容,以及mock接口模块化等

有用,谢谢!

已经成功抄袭该方法,很好用

mock 真的不错 最近在学习 ing ~~

21楼 已删除

如果现在有在使用的小伙伴可以把它完善就好了,或者遇到的问题也拿出来讨论一下,我也继续完善,想应该如何管理mock测试用例

谢谢分享,正想搞一套mock环境

请教一下:anyproxy设置抓包,ios客户端是正常的。但是android客户端能抓到接口请求,但是返回状态是503,且mime type是html格式(不是json格式)。请问有遇到这个问题么。。。

楼主可知道从 github 上下载下来的源码,如何启动呢?

#25楼 @michael_wang 找到方法了,如下
在项目根路径下执行

npm install

会自动安装依赖模块,在根路径自动生成 node_modules 文件夹,然后继续执行下面命令即可启动

node bin.js

#24楼 @aifeiyan 看看是不是数据提交错了,服务端有一些异常是不处理的,不处理或服务器挂了的话会返回50几的错误,那一般有像会返回html之类的

这个不错

问下楼主,接口业务很多,只想mock指定接口,其它接口走线上,想mock的接口规则不一样,必须每个接口一个规则,像这种规则如何定义?另外anyproxy一旦当有新规则添加时,都需要重新启动,这个咋解决?

谢谢分享

我们公司接口是加密了的,把要返回的json串➕request 的header里的token 再加其他的参数做加密,最终返回加密后的base64字节串。想法是截取到token ,调用Python脚本根据预先定义好的json结果串生成加密后的密文,再把这密文加到moco的返回结果里。但看了下moco文档,不支持,对于我这种情况有什么方法解决吗?

#31楼 @tavisdxh 其实后来改进了方案,放弃了moco,当初用moco其实只是为了解决数据分离管理的问题,后面发现直接用Anyproxy去读json文件效果也是一样的,所以把你的数据直接写在json上用rule.js去读取就好了

33楼 已删除
terrychow 基于 Anyproxy 的 Mock 服务器设计优化升级 中提及了此贴 04月28日 01:54

不实用,感觉moco服务,取本地json数据,光自己写匹配规则就非常难写,已弃坑😂

37楼 已删除
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册