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

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

一、前言

  • 这次分享主要和 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楼 已删除
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册