现因系统需要对接各种第三方平台,但是因为:
故使用MockLab来模拟第三方平台,辅助测试人员测试。
MockLab不仅仅可以应用于这些场景,还可以:
MockLab是基于WireMock,类同于WireMock的在线版,地址为MockLab。
MockLab需要注册账户并登录后才可以使用,且免费版对api的个数有要求,具体参考MockLab的说明文档。
详细内容可以参考说明文档。
1.新增Mock API
输入APIname、hostname,保存即可。
2.新增API
输入name、url和response,保存即可。
3.发送请求测试
4.1.1匹配URLs
例如:匹配规则是
/my/path?q=abc&limit=10
请求URL是
A:https://my-api.mocklab.io/my/path?q=abc
B:https://my-api.mocklab.io/my/path?q=abc&limit=10
C:https://my-api.mocklab.io/my/path
D:https://my-api.mocklab.io/my/path?randomqueryparam=123
如果匹配策略是path时,ABCD都可以匹配。
如果匹配测试是path + query时,B才可以匹配,ACD匹配失败。
例如:匹配规则是
/users/[0-9]+?q=[a-zA-Z]{1,4}&limit=10
请求URL是
A:/users/1
B:/users/9832749823?q=abc&limit=10
C:/users/321?q=abcde&limit=10
D: /users/9832749823?p=abc&limit=10
如果匹配策略是pathregex时,ABCD都可以匹配。
如果匹配测试是path + query regex时,B才可以匹配,ACD匹配失败。
4.1.2匹配JSON请求
equalToJson
仅当输入JSON中的所有元素都与期望的JSON相同,数组的顺序相同并且不存在其他元素时,才会匹配。字典中的元素顺序不会影响匹配。
可选择:
如果要检查是否存在某个元素,但是不在乎值是什么,则可以使用JSONUnit占位符语法来实现。使用${json-unit.ignore}时,元素的类型也将被忽略(除了其值之外)。
如果要将元素限制为特定类型,但仍然忽略该值,则可以使用以下占位符之一:
${json-unit.regex}[A-Z]+ (可以使用任何Java风格的正则表达式)
${json-unit.any-string}
${json-unit.any-boolean}
${json-unit.any-number}
matchesJsonPath
允按照指定的Xpath路径去匹配元素。
可选择:
常见的匹配示例:
1.按位置匹配特定数组元素
$.sizes[1]
equal to
M
将匹配:
{
"sizes":["S", "M", "L"]
}
匹配通过另一个元素找到的对象的一个元素。
$.addresses[?(@.type == 'business')].postcode
contains
N11NN
将匹配:
{
"addresses":[
{
"type":"home",
"postcode":"Z55ZZ"
},
{
"type":"business",
"postcode":"N11NN"
}
]
}
contains
在此实例中必须使用包含查询部分(在[?
和之间]
)的JSONPath表达式,该表达式将始终返回结果集合。
递归匹配匹配的元素。
$..postcode
contains
N11NN
将匹配:
{
"addresses":[
{
"type":"home",
"postcode":"Z55ZZ"
},
{
"type":"business",
"postcode":"N11NN"
}
]
}
并且还将匹配:
{
"address":{
"type":"business",
"postcode":"N11NN"
}
}
4.1.3匹配XML正文
Xml和json的匹配方式有些类似。
equalToXml
匹配操作者进行对照预期XML输入XML的语义比较,它会忽略空白中的差异、忽略元素和属性顺序。如果所有元素和属性都存在,具有相同的值并且没有其他元素或属性,则默认情况下会将输入与期望的XML匹配。
如果要检查是否存在某个元素,但是不在乎值是什么,则可以使用XMLUnit占位符语法来实现。使用${xmlunit.ignore实现。
matchesXPath
允按照指定的Xpath路径去匹配元素。
常见的匹配示例:
按位置匹配元素
/things/thing[@name = 'socks']
将匹配:
{
"sizes":["S","M","L"]
}
匹配通过另一个元素找到的对象的一个元素。
$.addresses[?(@.type == 'business')].postcode
contains
N11NN
将匹配:
4.1.4匹配类型
MockLab(通过WireMock)支持一组匹配操作,可用于请求的查询,标头,Cookie和正文。且同一种匹配支持多个。
4.2.1基础
响应可以通过使用模板对响应的内容的进行模拟化
通过在“响应”部分中选中“启用模板”框来启用存根模板:
勾选此框意味着可以对header和body进行模板化。
4.2.2条件逻辑和迭代
条件逻辑
常见的if / else if / else逻辑
{{#ifshowVariantA}}id="var-a">...{{elseifshowVariantB}}id="var-b">...{{elseifshowVariantC}}id="var-c">...{{else}}id="default-var">...{{/if}}
如果条件为假,则可以执行以下操作unless
{{#unlesshideDetails}}id="details">...{{/unless}}
比较函数
如果您需要检查变量是否等于特定字符串,则可以使用eq
{{#eqname'Dan'}}id="dan">...{{elseeqname'Mark'}}id="mark">...{{else}}id="anon">...{{/eq}} 比较函数:
{{#eqname'Jeff'}}...{{/eq}}
{{#neqname'Jeff'}}...{{/neq}}
{{#gtitemCount3}}...{{/gt}}
{{#gteitemCount3}}...{{/gte}}
{{#ltitemCount3}}...{{/lt}}
{{#lteitemCount3}}...{{/lte}}
{{#and(ltitemCount10)(gtitemCount5)}}...{{/and}}
{{#or(eqitemCount1)(eqitemCount2)}}...{{/or}}
{{#not(eqitemCount1)}}...{{/not}}
4.2.3迭代
使用each来循环收集数据,例如
{{#eachrequest.query.thingsas|thing|}} thing: {{{thing}}}
{{/each}}
例如:
{{#each(jsonPathrequest.body'$.things')as|thing|}} {{#if@last}}{ "thing": {{{thing}}} }
{{else}}{ "thing": {{{thing}}} },
{{/if}} {{/each}}
{{#each(jsonPathrequest.body'$.things')as|thing|}} {{@index}}: {{thing}} {{/each}}
4.2.4字符串
正则表达式
正则表达式提取可以提取单个值,例如
{{regexExtractrequest.body'[A-Z]+'}}
也可以将多个部分提取到对象中以供以后使用(最后一个参数是将为其分配对象的变量名称),例如
{regexExtractrequest.body'([a-z]+)-([A-Z]+)-([0-9]+)''parts'}{{parts.0}},{{parts.1}},{{parts.2}}
字符串转换
{{trimrequest.headers.X-Padded-Header}} // Inline
{{#trim}} // Block Some stuff with whitespace
{{/trim}}
{{abbreviate'Mocking APIs helps you develop faster'21}} // Mocking APIs helps...
{{capitalize'mock my stuff'}} // Mock My Stuff
{{capitalizeFirst'mock my stuff'}} // Mock my stuff
{{center'hello'size=21}}
将输出:
hello
您还可以指定填充字符,例如
{{center'hello'size=21pad='#'}}
将输出:
########hello########
{{cut'mocking, stubbing, faults'','}} // mocking stubbing faults
{{defaultIfEmpty'my value''default'}} // my value {{defaultIfEmpty'''default'}} // default
{{join'Mark''Rob''Dan'', '}} // Mark, Rob, Dan
您可以选择指定前缀和后缀:
{{join'Mark''Rob''Dan'', 'prefix='['suffix=']'}} // [Mark, Rob, Dan]
{{ljust'things'size=20}} // 'things ' {{ljust'things'size=20pad='#'}} // 'things##############'
rjust 以相同的方式将值右对齐
{{rjust'things'size=20}} // ' things'
{{rjust'things'size=20pad='#'}} // '##############things'
{{lower'MockLab'}} // mocklab {{upper'MockLab'}} // MOCKLAB
{{replace'the wrong way''wrong''right'}} // the right way
slugify
转换为小写字母,删除非单词字符(字母数字和下划线),并将空格转换为连字符。还去除前导和尾随空格。
{{slugify'Mock my APIs'}} // mock-my-apis
stripTags
剥离所有
[X] HTML
标记。
{{stripTags'hi '}} // hi
substring
输出两个索引之间的字符串值部分。如果仅指定一个索引,则将返回此点和结尾之间的子字符串。
{{substring'one two'4}} // two {{substring'one two'03}} // one
wordWrap
以指定的行长包装单词。
{{wordWrap'one two three'4}}
将输出:
one
two
three
yesno
将
true
,
false
和可选的
null
值映射到字符串
“ yes”
,
“ no”
,
“ maybe”
。
{{yesno true}} // yes {{yesno false}} // no {{yesno null}} // maybe
您还可以指定不同的字符串来表示每个状态:
{{yesno trueyes='aye'}} // aye {{yesno falseno='nay'}} // nay {{yesnonullmaybe='meh'}} // meh
字符串编码
{{{base64request.headers.X-Plain-Header}}} {{{base64request.headers.X-Plain-Headerpadding=false}}} {{{base64request.headers.X-Encoded-Headerdecode=true}}} {{{#base64}}}Content to encode {{{/base64}}} {{{#base64decode=true}}}Q29udGVudCB0byBkZWNvZGUK{{{/base64}}}
{{{urlEncoderequest.headers.X-Plain-Header}}} {{{urlEncoderequest.headers.X-Encoded-Headerdecode=true}}} {{{#urlEncode}}}Content to encode {{{/urlEncode}}} {{{#urlEncodedecode=true}}}Content%20to%20decode {{{/urlEncode}}}
将请求主体解析为表单,然后输出单个字段formField3:
{{formDatarequest.body'form'urlDecode=true}}{{{form.formField3}}
如果提交的表单具有给定字段的多个值,则可以通过索引访问这些值:
{{formDatarequest.body'form'urlDecode=true}}}{{{form.multiValueField.1}}, {{{form.multiValueField.2}} {{formDatarequest.body'form'urlDecode=true}}}{{{form.multiValueField.first}}, {{{form.multiValueField.last}}
4.2.5日期和时间
当前日期/时间
Now:呈现当前日期/时间,以指定格式的能力
{{now}} {{nowoffset='3 days'}} {{nowoffset='-24 seconds'}} {{nowoffset='1 years'}} {{nowoffset='10 years'format='yyyy-MM-dd'}}
日期可以在特定时区(默认为UTC)呈现:
{{nowtimezone='Australia/Sydney'format='yyyy-MM-dd HH:mm:ssZ'}}
通过epoch作为格式来呈现日期作为UNIX信号出现时间(毫秒),或unix如以使以秒为UNIX时间戳的格式。
{{nowoffset='2 years'format='epoch'}} {{nowoffset='2 years'format='unix'}}
已存在的日期值:更改偏移量,时区和打印格式
{{datemyDateoffset='-1 days'timezone='EST'format='yyyy-MM-dd'}}
从字符串解析日期
{{date(parseDaterequest.headers.MyDate)offset='-1 days'}}
格式化日期
使用dateFormat助手将日期值格式化为字符串。您可以从以下选项中选择一种命名格式:
例如
{{dateFormat(parseDate'2020-01-01T11:11:11Z')'full'}} // Wednesday, January 1, 2020
或者,您可以指定自己的格式字符串(在此完整参考):
{{dateFormat(parseDate'2020-01-01T11:11:11Z')format='yyyy-MM-dd'}} // 2020-01-01
格式化和解析日期和时间时使用的所有格式字符串元素:
4.2.6随机值
randomValue
randomValue辅助生成特定类型和长度的随机串。(可选)可以通过uppercase参数将包含字母字符的值设为大写。
{{randomValuelength=33type='ALPHANUMERIC'}}{{randomValuelength=12type='ALPHANUMERIC'uppercase=true}}{{randomValuelength=55type='ALPHABETIC'}}{{randomValuelength=27type='ALPHABETIC'uppercase=true}}{{randomValuelength=10type='NUMERIC'}}{{randomValuelength=5type='ALPHANUMERIC_AND_SYMBOLS'}}{{randomValuetype='UUID'}}
pickRandom
pickRandom辅助随机地从它的参数的值
如果第一个参数是一个集合,则将从该值中随机选择值:
// Assume that numberList = [1, 2, 3]
{{pickRandomnumberList}} // One of 1, 2 or 3
否则将从提供的参数列表中选择一个值:
{{pickRandom'1''2''3'}} // One of 1, 2 or 3
4.2.7XML
XPath
XPATH用于从请求正文中提取值
例如,给定一个请求主体:
Stuff
以下将“ Stuff”呈现到输出中:
{{{xPathrequest.body'/outer/inner/text()'}}}
给定相同的XML,将呈现以下内容
{{{xPathrequest.body'/outer/inner'}}}
XPath还允许提取属性,例如针对以下请求主体:
id="123"/>
下面将在输出中呈现“ 123”:
{{{xPathrequest.body'/outer/inner/@id'}}}
遍历XML元素
例如,给定一个形式的请求正文:
One Two Three 和以下模板:
{{#each(xPathrequest.body'/stuff/thing')as|element|}}{{{element.text}}}{{/each}}
结果输出将是:
One Two Three
XML元素属性
xPath具有以下属性:
text:元素的文本内容。
name:元素的名称。
attributes:已选择属性名称和值的映射,例如给定XML元素:
id="123"position="top"/>
可以引用其属性:
ID: {{{element.attributes.id}}}
Position: {{{element.attributes.position}}}
4.2.8JSON
JsonPath
将使用JSONPath表达式语言从JSON文档中提取值,通过查询表达式选择单个值或子文档。
例如,给定JSON
{"outer":{"inner":"Stuff"}}
以下将“ Stuff”呈现到输出中:
{{jsonPathrequest.body'$.outer.inner'}}
对于相同的JSON,将呈现以下内容{ "inner": "Stuff" }:
{{jsonPathrequest.body'$.outer'}}
遍历JSON元素
例如,给定一个形式的请求正文:
{"things":[{"id":1},{"id":2},{"id":3}]}
以及以下响应正文模板:
{{#each(jsonPathrequest.body'$.things')as|thing|}}thing: {{{thing.id}}}{{/each}}
响应主体将包含:
thing: 1
thing: 2
thing: 3
又如,给定请求JSON:
{"things":{"one":1,"two":2,"three":3}}
和模板:
{{#each(jsonPathrequest.body'$.things')as|valuekey|}}{{{key}}}={{{value}}}{{/each}}
输出将包含:
one=1
two=2
three=3
JSON Web令牌(JWT)
jwt
和jwks
都支持
HS256
(共享机密)和
RS256
(公钥
/
私钥)
生成令牌
可以通过启用模板并将以下内容简单地添加到respbse主体中来在存根响应中生成令牌:
{{{jwtmaxAge='12 days'}}}
到期日
可以通过设置maxAge参数自定义到期期限,例如
{{{jwtmaxAge='12 days'}}}
或通过设置绝对到期日期,例如
{{{jwtexp=(parseDate'2040-02-23T21:22:23Z')}}}
您可以类似地设置nbf(不早于)日期:
{{{jwtnbf=(parseDate'2018-02-23T21:22:23Z')}}}
其他
其他可参考帮助文档
https://www.mocklab.io/docs/response-templating/jwt/
4.3.1高级匹配
正文匹配
有必要根据帖子正文返回不同的响应(因为URL始终相同)
单击按钮添加子句,从下拉列表中选择匹配类型,然后将期望值或表达式写(或粘贴)到文本区域
请求优先级匹配
在列表中有多个存根映射与给定请求匹配的情况下,优先级较高的请求(即较低数量的请求)将首先匹配。
URL匹配
URL匹配包括以下:
高级请求参数匹配
除URL和正文外,请求还可以匹配:
添加多个match子句后,请求必须与所有子句都匹配才能送达响应(它们与逻辑AND结合在一起)
匹配JSON请求主体
JSON格式的请求主体存在两种特定的匹配类型:equalToJsonequals(matchesJsonPath)和JSONPath()。
匹配的XML请求主体
与JSON匹配一样,有两种可用于XML的匹配类型:equalToXml和matchesXPath
响应延迟
固定延迟
固定的延迟会在为响应提供服务之前直接增加指定毫秒数的暂停。
随机延迟
随机延迟会在提供响应之前添加随机暂停。有两种统计分布:
Fault
实际的API和用于与它们进行通信的网络可能会以破坏您的应用程序的方式失败,并且难以测试。
MockLab支持使用四种不同的故障类型来响应请求:
Simulating Fault
Simulating FaultwithScenarios
假设有一个用于获取列表的“列表待办事项” API调用,则在上述测试期间必须两次调用该方法,第一次调用不返回任何项,第二次调用则新添加的项。由于这两个请求都是相同的(相同的URL,方法,请求标头),因此MockLab需要额外的内容来区分第一种情况和第二种情况。
例如:
创建一个空列表api,仅当名为“待办事项”的方案处于“已启动”状态时,该空api才匹配
然后创建一个api来处理第一个列表项的发布。触发时,此存根会将方案状态移至“添加的第一项”:
最后,创建一个存根以返回包含一个项目的列表,只有当场景处于“添加的第一项目”状态时,该列表才被匹配:
首先,GET请求获取列表,该列表应该为空。您应该可以执行任意次此操作,而不会改变结果:
$ curl http://example.mocklab.io/todo-items
{
"items": []
}
现在POST是一个新项(实际上,请求主体包含什么都没有关系,因为我们没有在存根中指定主体匹配器):
$ curl http://example.mocklab.io/todo-items -X POST
现在,这应该已经将方案状态移动到“添加的第一项”。现在再次获取项目列表应该返回一个项目:
$ curl http://example.mocklab.io/todo-items
{
"items": [
{
"id": "1",
"description": "Read all about Scenarios"
}
]
}
背景:物流对接物润时测试物润返回异常
创建并配置api
物流测试环境的appllo配置
触发上传后,会根据模拟桩的配置返回响应,具体响应因特殊情况在Rancher中查看日志