匹配规则说明

模客支持多种基于 HTTP 协议的匹配,她会根据获得的 Http Request,在所有当前生效的规则中找到最为符合的一条,然后返回预先定义好的 Http Response

下面具体的规则说明中会涉及样例,样例中的规则定义将用系统截图形式给出,进行匹配的 Http Requestcurl 工具发送。

URL匹配

URL匹配是最基本的匹配方式,当不存在 Http Body 的情况下(GET请求),就会直接使用 URL 匹配获取适合的 Http Response。当有 Http Body 的情况下(POST或者PUT请求),也会先匹配 URL,然后再匹配 Http Body

简单的URL匹配例子

规则定义如下:

实际请求1:

curl -G 'mock-api.com/identity.mock/foo/bar'

——成功匹配上面的规则,Response返回“url matched.”。

实际请求2:

curl -G 'mock-api.com/identity.mock/bar/foo'

——url不符合,没有匹配到适合的规则,Response返回空字符串。

带查询参数的URL匹配例子

同时定义了2条规则,参数不同,如下:

实际请求1:

curl -G 'mock-api.com/identity.mock/url?foo=1'

——成功匹配上面的规则1,Response返回“url parameters [foo=1] matched.”。

实际请求2:

curl -G 'mock-api.com/identity.mock/url?foo=3'

——url参数不符合,没有匹配到适合的规则,Response返回空字符串。

实际请求3:

curl -G 'mock-api.com/identity.mock/url?foo=1&bar=2'

——成功匹配上面的规则2,Response返回“url parameters [foo=1&bar=2] matched.”。

实际请求4:

curl -G 'mock-api.com/identity.mock/url?foo=1&bar=3'

——满足了规则1的参数条件,虽然比规则1多了参数,仍然可以匹配成功,这样带来的好处是在模拟器规则定义时只需要关注接口已知的参数,不需要罗列出所有参数;Response返回“url parameters [foo=1] matched.”。

实际请求5:

curl -G 'mock-api.com/identity.mock/url?foo=1&bar=2&foobar=3'

——同时满足多个规则的情况下,会选取参数匹配的最多的规则;规则2匹配到了2个参数,多于规则1的1个参数,所以规则2成功匹配,Response返回“url parameters [foo=1&bar=2] matched.”。

基于Http Body的内容匹配

Body内容匹配是在有 Http Body 的情况下(POST或者PUT请求),并且URL匹配成功后(简单匹配或者参数匹配成功),系统自动识别 Http Body 可能的类型,当前支持的类型有 Text文本/Json/Xml 3种,然后找出最适合的规则。

Text文本匹配例子

规则定义如下:

实际请求1:

curl -G 'mock-api.com/identity.mock/text'

——这时候虽然url与规则定义的一致,但GET请求并没有Body,所以没有规则被匹配,Response返回空字符串。

实际请求2:

curl -H "Content-Type: text/plain" --data-raw 'foobar' 'mock-api.com/identity.mock/text'

——url与body内容都和规则一致,匹配成功,Response返回“text body matched.”。

实际请求3:

curl -H "Content-Type: text/plain" --data-raw 'foo bar' 'mock-api.com/identity.mock/text'

——文本匹配的整个body内容必须完全一致,包括所有白空格;上面的请求内容里多了一个空格,所以没有规则被匹配,Response返回空字符串。

Json匹配例子

规则定义如下:

实际请求1:

curl -H "Content-Type: application/json" --data-raw '{"foo":1,"bar":2}' 'mock-api.com/identity.mock/json'

——url与body内容都和规则一致,Json匹配只关注Json本身的对象属性和值,不用匹配没有意义的空格;匹配成功,Response返回“json body matched.”。

实际请求2:

curl -H "Content-Type: application/json" --data-raw '{"bar":2,"foo":1}' 'mock-api.com/identity.mock/json'

——Json匹配不需要关心同一个对象下的属性顺序;虽然foo属性和bar属性出现的次序不同,但这2个Json对象是等价的,匹配成功,Response返回“json body matched.”。

实际请求3:

curl -H "Content-Type: application/json" --data-raw '{"foo":2,"bar":2}' 'mock-api.com/identity.mock/json'

——foo属性的值与规则定义中的不一致,没有规则被匹配,Response返回空字符串。

实际请求4:

curl -H "Content-Type: application/json" --data-raw '{"foo":1,"bar":2,"foobar":3}' 'mock-api.com/identity.mock/json'

——Json对象多出了一个foobar属性(属性缺失同样会匹配失败),与规则定义中的不一致,没有规则被匹配,Response返回空字符串。

Xml匹配例子

规则定义如下:

实际请求1:

curl -H "Content-Type: application/xml" --data-raw '\\ value \</bar>\</foo>' 'mock-api.com/identity.mock/xml'

——url与body内容都和规则一致,Xml匹配同样只关注Xml本身的结构,不用匹配没有意义的空格;匹配成功,Response返回“xml body matched.”。

实际请求2:

curl -H "Content-Type: application/xml" --data-raw '\\value\</bar>\</foo>' 'mock-api.com/identity.mock/xml'

——标签的属性值必须是全部匹配的,包括空格;bar标签的attr属性值多了头尾2个空格,所以没有规则被匹配,Response返回空字符串。

实际请求3:

curl -H "Content-Type: application/xml" --data-raw '\\value\</bar>\</foo>' 'mock-api.com/identity.mock/xml'

——标签或者属性缺失或者多余同样无法匹配(Xml的node是有次序的,所以单个node下的child node次序不对也无法匹配),Response返回空字符串。

通用内容匹配例子

如果定义了一个空字符的Text文本类型的规则,那将匹配所有带Body的相同url的请求,如下:

实际请求1:

curl -H "Content-Type: text/plain" --data-raw 'anything' 'mock-api.com/identity.mock/text'

——匹配成功,Response返回“text with empty body matched.”。

实际请求2:

curl -H "Content-Type: application/json" --data-raw '{"any":"json"}' 'mock-api.com/identity.mock/text'

——即使是Json或者Xml也能够匹配成功,只要url一致且含有body,所以这个通用规则一般在不了解具体接口,只是为了让mock测试跑起来时候使用;Response返回“text with empty body matched.”。

基于Form表单的匹配

Form表单匹配是当且仅当 Http RequestContent-Type 为[application/x-www-form-urlencoded]的情况(POST提交表单)下才会触发。

Form表单匹配的方式比较特殊,首先会匹配不带任何参数的url是否有一致的规则,然后会把 url 里的参数和 body 里的参数都统一作为Form表单参数来进行匹配,和之前的url参数匹配规则类似,具有匹配参数最多的规则将获胜。

定义Key-Value值来匹配表单的例子

规则定义如下:

实际请求1:

curl --data-raw 'foo=2&bar=1' 'mock-api.com/identity.mock/form'

——匹配成功,Response返回“form with form parameters [foo=2&bar=1] matched.”。

实际请求2:

curl -H "Content-Type: text/plain" --data-raw 'foo=2&bar=1' 'mock-api.com/identity.mock/form'

——虽然请求内容和请求1完全一样,但由于 Content-Type 为[text/plain];没有匹配成功,Response返回空字符串。

定义符合Form规范的Text文本来匹配表单的例子

规则虽然是Text文本类型,但系统会识别出这个文本符合Form定义,这样的规则即可以匹配Form请求,又可以匹配普通POST请求,比较灵活,如下:

实际请求1:

curl --data-raw 'foo=1&bar=2' 'mock-api.com/identity.mock/form'

——匹配成功,Response返回“form with text parameters [foo=1&bar=2] matched.”。

实际请求2:

curl -H "Content-Type: text/plain" --data-raw 'foo=1&bar=2' 'mock-api.com/identity.mock/form'

——不同于上一个规则,这次作为Text文本也能匹配成功,Response返回“form with text parameters [foo=1&bar=2] matched.”。

混合Url参数来匹配表单的例子

当规则是Form表单类型时,url里的参数也被视作表单参数,规则定义如下:

实际请求1:

curl --data-raw 'foo=bar&bar=foo' 'mock-api.com/identity.mock/form'

——规则定义中包含在url里的foo=bar参数可以匹配实际请求中的参数,Response返回“form with both url [foo=bar] and map parameters [bar=foo] matched.”。

实际请求2:

curl --data-raw 'foo=bar' 'mock-api.com/identity.mock/form?bar=foo'

——参数一视同仁,body里的可以和url里的互换,Response返回“form with both url [foo=bar] and map parameters [bar=foo] matched.”。

通用表单匹配的例子

和通用内容匹配类似,表单匹配也可以有通配规则,即一个Key-Value都不填,那将匹配所有 Content-Type 为[application/x-www-form-urlencoded]的相同url的请求,如下:

实际请求1:

curl --data-raw 'any=form' 'mock-api.com/identity.mock/form'

——匹配成功,Response返回“form with empty map parameters matched.”。

基于表达式的匹配

表达式匹配是上面那些基础匹配功能的增强,能够实现非常灵活的匹配规则,相当于一个接口请求模版。比如同一条规则可以用来支持多个模拟接口,或者支持同一接口的不同请求实例。非常适合使用在测试接口变动比较大,或者测试案例需要模拟的实例化数据特别多的情况下

表达式匹配支持基于 Apache common-jexl 版本3的表达式语法。同时还内置了:

  • $_url 对象,用来获取 Http Request 中的 url(“mock-api.com/identity.mock/”之后的部分),类型为String
  • $_body 对象,用来获取 Http Request 中的 body,类型为String
  • $_header 对象,用来获取 Http Request 中的 header,类型为Map
  • $_param 对象,用来获取 Http Request 中的 Parameter,类型为Map

  • $_json.is(String str) 方法,用来判断参数str是否为合法的Json对象,返回类型为boolean
  • $_json.path(String json, String path) 方法,用来获取某个json对象里的具体值,返回类型为String,无法解析Json或者jsonPath时返回"null" (JsonPath语法参考)

  • $_xml.is(String str) 方法,用来判断参数str是否为合法的Xml文档,返回类型为boolean
  • $_xml.path(String xml, String xpath) 方法,用来获取某个Xml文档对象里的具体值,返回类型为String,无法解析Xml或者xPath时返回"invalid"

Url表达式匹配的例子

希望通过表达式来匹配所有url为 api/user/{uid} 的形式,其中uid希望是数字,所以可以使用正则表达式.*/user/\d+这种api在restful接口中很常见,规则定义如下:

实际请求1:

curl -G 'mock-api.com/identity.mock/api/user/1'

——匹配到id为1的user,Response返回“url expression [$_url =~ ".*/user/\d+"] matched.”。

实际请求2:

curl -G 'mock-api.com/identity.mock/api/user/foobar'

——虽然url匹配上了,但最后的uid并不是期望中的数字形式,没有匹配成功,Response返回空字符串。

实际请求3:

curl -G 'mock-api.com/identity.mock/foobar/user/1'

——虽然表达式符合要求,但url并不是以规则中填写的起始,同样没有匹配成功,Response返回空字符串。

Body中字符串匹配的例子

希望匹配所有 Bodystr起始的请求,规则定义如下:

实际请求1:

curl -H "Content-Type: text/plain" --data-raw 'string' 'mock-api.com/identity.mock/expression'

——匹配成功,Response返回“body starts with "str" matched.”。

Header中字符串匹配的例子

希望匹配所有 Header中的cookie等于str的请求,规则定义如下:

实际请求1:

curl -H "Content-Type: text/plain" -H "Cookie : str" --data-raw 'xxx' 'mock-api.com/identity.mock/expression'

——匹配成功,Response返回“header.cookie equal str matched.”。

JsonPath匹配的例子

希望匹配所有 Body 是Json对象,并且bar属性的p2数组的第一个值等于1的请求,规则定义如下:

实际请求1:

curl -H "Content-Type: application/json" --data-raw '{"foo":"ok","bar":{p1:1, p2:[1,2,3]}}}' ''mock-api.com/identity.mock/expression'

——匹配成功,Response返回“value of json path "$.bar.p2[0]" equals 1 matched.”。

XPath匹配的例子

希望匹配所有 Body 是Xml文档,并且其中attr属性为true的标签的文本内容等于value,规则定义如下:

实际请求1:

curl -H "Content-Type: application/xml" --data-raw '\\value\</bar>\</foo>' ''mock-api.com/identity.mock/expression'

——匹配成功,Response返回“value of xpath "//bar[@attr='true']/text()" equals "value" matched.”。

匹配的优先级

METHOD URL HEADER BODY

GET DELETE 没有BODY PUT POST

  • 非表单匹配时的优先级如下:

    1. url一致,并且body内容(如果有)作为文本一致
    2. url一致,并且body内容(如果有)作为Json一致
    3. url一致,并且body内容(如果有)作为Xml一致
    4. url一致,并且整个请求符合表达式定义
    5. url一致,并且设置了通用body内容匹配规则
    6. 基本url一致,且url参数匹配,并且body内容(如果有)作为文本一致
    7. 基本url一致,且url参数匹配,并且body内容(如果有)作为Json一致
    8. 基本url一致,且url参数匹配,并且body内容(如果有)作为Xml一致
    9. 基本url一致,且url参数匹配,并且整个请求符合表达式定义
    10. 基本url一致,且url参数匹配,并且设置了通用body内容匹配规则
    11. url以规则定义中的url以规则定义中的url开始,并且整个请求符合表达式定义,且表达式中有$_url参数
  • 表单匹配时的优先级如下:

    1. url一致,并且没有任何Form表单参数
    2. 基本url一致,且Form表单参数(同时包括urlbody中定义的参数)匹配
    3. 基本url一致,并且整个请求符合表达式定义
    4. url以规则定义中的url以规则定义中的url开始,并且整个请求符合表达式定义,且表达式中有$_url参数

响应模版

Http Response 内容的编辑支持 Apache Velocity 1.7版本的语法。

支持 Velocity 提供的几种基本的 GenericTools

  • $date 对象,用来对时间类型的值进行格式化或者运算,详细使用方法参考 DateTool Javadoc
  • $number 对象,用来对数字类型的值进行格式化,详细使用方法参考 NumberTool Javadoc
  • $math 对象,用于数学运算,详细使用方法参考 MathTool Javadoc

同样也内置了:

  • $_url 对象,用来获取 Http Request 中的 url(“mock-api.com/identity.mock/”之后的部分),类型为String
  • $_body 对象,用来获取 Http Request 中的 body,类型为String
  • $_param 对象,用来获取 Http Request 中的 parameter,类型为Map,如:$_param、$_param['foo'] $_param.foo
  • $_cookie 对象,用来获取 Http Request 中的 cookie,类型为Map,如:$_cookie['JSESSIONID']
  • $_header 对象,用来获取 Http Request 中的 header,类型为Map,如:$_header['User-Agent']

  • $_json.is(String str) 方法,用来判断参数str是否为合法的Json对象,返回类型为boolean
  • $_json.path(String json, String path) 方法,用来获取某个json对象里的具体值,返回类型为String,无法解析Json或者jsonPath时返回"null" (JsonPath语法参考)

  • $_delay.method(int ms) 方法,用来延时响应,参数单位:毫秒

  • $_callBack.method(String body, String url, String methodType) 方法,用来回调,入参body
  • $_callBack.methodParam(String jsonParam, String url, String methodType) 方法,用来回调,入参jsonParam
  • $_callBack.scheduledParam(final String jsonParam, final String url, final String methodType, int delayMs) 方法,用来定时回调,异步操作,入参jsonParam
  • $_callBack.scheduledBody(final String body, final String url, final String methodType, int delayMs) 方法,用来定时回调,异步操作,入参body

  • $_xml.is(String str) 方法,用来判断参数str是否为合法的Xml文档,返回类型为boolean
  • $_xml.path(String xml, String xpath) 方法,用来获取某个Xml文档对象里的具体值,返回类型为String,无法解析Xml或者xPath时返回"invalid"

响应模版的例子

期望匹配一个 bodyjsongreet 接口api,规则定义如下:

实际请求1:

curl -H "Content-Type: application/json" --data-raw '{"name":"foo","count":5}' ''mock-api.com/identity.mock/greet'

——匹配成功,Response返回“Hello, for!\n 6 times you visit [greet] api.\n --2016-2-29 16:39:54”。

响应里面的高亮值都是在服务器端根据不同的请求生成的。

实际请求2:

curl -H "Content-Type: application/json" --data-raw '{"name":"bar","count":100}' ''mock-api.com/identity.mock/greet'

——匹配成功,Response返回“Hello, bar!\n 101 times you visit [greet] api.\n --2016-2-29 16:44:26”。