系统测试利器之挡板实战(三)

mb详解

上面主要介绍了mb的环境安装及其关键术语,和一个简单的demo,那么接下来我们逐步了解。

其他语言客户端支持

如果你对nodejs不熟或者很倔不想接收新的语言,可以在下面找到自己的熟悉的语言,如果没有要自己去写了。
说实在的,对于有上心的开发者是难不倒的,一点就通!

语言 工程 作者
C# MbDotNet Matthew Herman
Clojure Charlatan Matthew Daley
Go GoBank Erkan
Java javabank James Thomas
JavaScript mountebank-helper Alex
Perl Test::Mountebank Dagfinn Reiersøl
PHP Juggler Andrejs Mironovs
Python mountepy Michał Bultrowicz
Ruby mountebank-gem Michael Cheng
Shell mountebank-sh Sergi Bech Robleda
TypeScript node-mountebank Ron van der Wijngaard

启动脚本

看到这里应该明白了mb究竟是个什么东东,但怎么开发、启动一个自己的服务估计还有些迷糊,那么我们从启动说起。

mb start --configfile imposters.ejs  --allowInjection  &

上面我说了常用的参数,这个启动指令里包含 start、--configfile、--allowInjection。

start顾名思义就是启动mb

--configfile 后面跟的imposters.ejs就是模板文件,EJS是一个JavaScript模板库,用来从JSON数据中生成HTML字符串。
有时通过配置文件加载imposters更方便,而不是通过API(就是通过指令,我也嫌麻烦就没提)加载它们。
我们可以在EJS文件里面定义端口、通讯协议、存根等,对于多个服务的模块化开发相当便利。

--allowInjection 是否允许脚本注入,后面详解。

EJS文件脚本

本次讲解主要是http的挡板服务,由于时间有限,smtp、tcp请参照官方文档或等后续文档。

imposters.ejs文件的内容是json格式的数据,具体如下:

{
    "imposters": [
        <% include ./test/test1.json %>,
        <% include ./test/test2.json %>,
        <% include ./test/test3.json %>
    ]
}

ejs内容比较简单,就是imposters的配置,它是json数组,通过include加载多个json文件来注入到imposters配置中,如test1.json是支付的挡板代码,
test2.json是实名认证的挡板代码,这样从架构的角度,各司其职、分而治之不同的业务挡板不同的配置文件,便于并行开发和维护。

JSON文件脚本

test1.json文件json的格式如下,可以根据注释了解其整个结构。

{
    "port": 1234,<!-- 指定端口 -->
    "protocol": "http",<!-- 指定协议 -->
    "stubs": [{<!-- 可以多个元素 -->
        "predicates": [{
                "equals": {<!-- 如果请求url 为/test/demo时触发本stub-->
                    "path": "/test/demo",<!-- 访问路径 -->
                    "method": "post"<!-- 提交方法 -->
                }
            }, {}],<!-- 可以多个元素 -->
        "responses": [{
            "is": {
                "statusCode": 200,
                "headers": {
                },
                "body": {
                }
            },
            "_behaviors": {
                "shellTransform": ["node ./test/test.js"]<!-- 脚本注入 -->
            }
        }, {}]<!-- 可以多个元素 -->
    },
    {<!-- 请求不匹配时响应内容,如果没有谓词匹配,则发送默认响应 -->
        "responses": [{
            "is": {
                "statusCode": 400,<!-- 服务器不理解请求的语法,这里可以随意定义的哈 -->
                "headers": {
                },
                "body": {
                }
            }
        }]
    }]
}

<font color="red">注意
最后一个应答是没有predicate匹配,则发送默认响应,就是我们写代码是swich时的default。
</font>

说起http协议,一定要说下状态码,有时候面试官也会经常问起,目前大多数服务化治理都是采用http通讯协议。

下面简单的提下,便于大家理解,技术这玩意也是个关系网,简单的服务也会涉及到很多领域。
做前端的兄弟们一定要记住,因为大多是中后台兄弟的问题,这个时候可以吊他们一次。

1开头系列:表示请求已接收,继续处理
100

2开头系列:成功--表示请求已被成功接收、理解、接受
200 ok 表示请求成功返回网页

3开头系列:表示重定向,要完成请求必须进行更进一步的操作
301 永久跳转
302 临时跳转,请求的网页已临时跳转到新位置。

4开头系列:客户端错误--请求有语法错误或请求无法实现
400 服务器不理解请求的语法。
401 请求要求身份验证。对于登录后请求的网页,服务器可能返回此响应。
403 表示用户得到授权(与401错误相对),但是访问是被禁止的,服务器收到请求但是拒绝提供服务
404 网页没有发现
406 用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。

5开头系列:服务器端错误--服务器未能实现合法的请求
500 内部服务器错误
502 一般是网关服务器请求后端服务时,后端服务没有按照http协议正确返回结果。
503 服务当前不可用, 可能因为超载或停机维护。
504 一般是网关服务器请求后端服务时,后端服务没有在特定的时间内完成服务。

protocol常用设置

协议这块http默认就可以了,https的话最好配置下私钥和证书,这样核心系统调用时不会出现警告。

{
  "port": 1234,
  "protocol": "https",
  "key": "",<!-- SSL服务器私钥 -->
  "cert": "",<!-- SSL服务器证书 -->
  ...
}

predicates常用配置

predicate决定存根是否匹配,不管怎样它返回就是一个boolean值,true或false,如果返回true就返回对应的response响应,只要这个清楚,那么下面的所有花哨都很一般。

常用运算符
运算符 描述
equals 请求字段与谓词匹配
deepEquals 在请求的数据包含某个关键字及对应的值(例如query,http中的字段)
contains 请求字段包含谓词
startsWith 请求字段以谓词开头
endsWith 请求字段以谓词结束
matches 请求字段与正则表达式匹配。
exists 是否存在
not 取反
or 满足其中一个条件
and 同时满足条件
inject 注入JavaScript以确定请求是否匹配
常用的条件设置

equals

{
    "port": 8081,
    "protocol": "http",
    "stubs": [{
        "predicates": [{
            "equals": {
                "path": "/test",
                "method": "get"
            }
        }],
        "responses": [{
            "is": {
                "body": {
                    "Operator": "equals"
                }
            }

        }]
    }]
}

浏览器访问后结果http://localhost:8081/test

{
    "Operator": "equals"
}

deepEquals

{
    "port": 8081,
    "protocol": "http",
    "stubs": [{
        "predicates": [{
            "deepEquals": {
                "query": {
                    "key": ["first", "second"]
                }
            }
        }],
        "responses": [{
            "is": {
                "body": {
                    "Operator": "deepEquals"
                }
            }

        }]
    }]
}

浏览器访问后结果http://localhost:8081/test?key=second&key=first

{
    "Operator": "deepEquals"
}

exists

{
    "port": 8081,
    "protocol": "http",
    "stubs": [{
        "predicates": [{
            "exists": {
            "method": true,
            "body": false
          }
        }],
        "responses": [{
            "is": {
                "body": {
                    "Operator": "exists"
                }
            }

        }]
    }]
}

浏览器访问后结果http://localhost:8081/test

{
    "Operator": "exists"
}

还有其他场景判断

"exists": {
            "method": true,<!-- get或post -->
            "body": false <!-- 没有body,就是get情况-->
          }
                    
"exists": { "body": true }<!-- post情况 -->

inject 脚本注入设置

{
    "port": 8081,
    "protocol": "http",
    "stubs": [{
        "predicates": [{
                "inject": "function (config) {return config.request.body.indexOf('inject') === 0;    }"
            }
        ],
        "responses": [{
            "is": {
                "body": {
                    "Operator": "inject"
                }
            }

        }]
    }]
}

通过postman post方法提交,http://localhost:8081/test,提交数据包含inject,返回结果如下:

{
    "Operator": "inject"
}

<font color="red">注意
inject的函数在这里不能进行编排,造成编写、调试代码不方便,可以采用下面导入文件的方式解决,包括responses注入也适应。
</font>

inject利用stringify导入模板脚本

{
    "port": 8081,
    "protocol": "http",
    "stubs": [{
        "predicates": [{
            "inject": "<%- stringify(filename, './test/inject.ejs') %>"
        }],
        "responses": [{
            "is": {
                "body": {
                    "Operator": "inject"
                }
            }

        }]
    }]
}

inject.ejs脚本

function(config) {
    return config.request.body.indexOf('mounte') === 0;
}

<font color="red">注意
其他的操作都是对tcp数据的操作,在这里不做过多解释,有需要可以和我沟通或去官网去查帮助。
</font>

xpath脚本
是挡板接收xml数据的时候进行条件的判断,由于我们的服务大多是基于restful的,所以这种场景使用不多,全凭烧下大脑,越来越聪明。

{
    "port": 8081,
    "protocol": "http",
    "stubs": [{
        "predicates": [{
            "equals": {
                "body": "Harry Potter"
            },
            "xpath": {
                "selector": "//title"
            },
            "caseSensitive": true,
            "comment": "case sensitivity applies to the selector as well as the value"
        }],
        "responses": [{
            "is": {
                "body": {
                    "Operator": "xpath"
                }
            }

        }]
    }]
}

通过postman post方法提交,http://localhost:8081/,提交数据如下:

<books xmlns:isbn="http://schemas.isbn.org/ns/1999/basic.dtd">
  <book>
    <title>Harry Potter</title>
    <isbn:summary>Dragons</isbn:summary>
  </book>
</books>

返回的结果如下:

{
    "Operator": "xpath"
}

caseSensitive区分大小写,true或false。

selector查找xml那个节点,本示例是查的title节点。

系统测试利器之挡板实战(一)
系统测试利器之挡板实战(二)
系统测试利器之挡板实战(四)
系统测试利器之挡板实战(五)
系统测试利器之挡板实战(六)
系统测试利器之挡板实战终结(七)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,179评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,229评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,032评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,533评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,531评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,539评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,916评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,813评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,568评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,654评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,354评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,918评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,152评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,852评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,378评论 2 342

推荐阅读更多精彩内容