美文网首页
系统测试利器之挡板实战(三)

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

作者: 老杜杂谈 | 来源:发表于2020-03-10 20:59 被阅读0次

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节点。

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

相关文章

网友评论

      本文标题:系统测试利器之挡板实战(三)

      本文链接:https://www.haomeiwen.com/subject/wczgdhtx.html