app 接口 mock server 端返回一工具,一剑在手,跟我走! app 崩溃就靠它了
app 对服务端返回的容错测试
服务端返回一旦出错后果很严重,app 轻则 ui 异常重则崩溃,像 api 404,502,长时间无返回,延迟, 返回空 body,键值错,无值,异常值这几类一般必测
项目中使用该工具后效率有了明显提升
app 通过 pc 上 fiddler 代理访问 api
通过运行 proxy xxx 给 mock server 注入 mock 配置,支持重置
借助 fiddlerscript 实现包转发给 mock server,server 根据运行时动态配置对包进行劫持修改,修改后再返还给 fiddler
fiddler.js 重写 OnBeforeResponse 将指定包劫持转发给 mockserver
static function OnBeforeResponse(oSession: Session) {
if (isautocap && oSession.HostnameIs(filterUrl) && oSession.responseCode == 200) {
oSession.utilDecodeResponse()
var rawbody = System.Text.Encoding.UTF8.GetString(oSession.responseBodyBytes);
var j=Fiddler.WebFormats.JSON.JsonDecode(rawbody)
if(typeof(j.JSONObject) == "object" && Object.prototype.toString.call(j.JSONObject).toLowerCase() == "[object hashtable]" && !j.JSONObject.length) {
try {
var api = oSession.PathAndQuery.split('?')[0]
rawbody = api + ':' + rawbody
var mockbody = mock('127.0.0.1', 8390, rawbody)
j=Fiddler.WebFormats.JSON.JsonDecode(mockbody)
mockserver.py 执行 mock
def prep(self,data):
api, data = data.split(':', 1)
data = json.loads(data, encoding="utf8")
mock = {}
data['mock'] = mock
if api in self.api or not self.api:
try:
data = self.mock('', data)
索引找 response 中的关键字,并修改这个项的值
def key(data):
for k in self.key:
v= self.value[k]
if ':' in k:
str,k = k.split(':',1)
if str.lower() in ['regex','re','regexp']: data = regexpsearch(data,k,v) #关键字或正则模糊查找
else:
l_key= k.split('.')
data = exactsearch(data,l_key,v) #精确查找
return data
mockfun = {
'body': lambda: body(self.body),
'key': lambda: key(data),
'': lambda: data,
'clear':lambda : self.init()}
return mockfun[self.type]()
修改的值可以是具体值或者 body,也可以是 fuzz 函数 也可自行实现其他 fuzz
def setstrshorten(json, k,v):
v=str(v)
json[k] = (len(v) <= 3) and v or v[0:len(v) - random.randint(1, len(v)-1)]
def setstroverlen(json, k,v):
v=str(v)
n = 1025
# n=4294967294 max string ,..dot use!
for i in range(0, n): v += '1'
json[k] = v
def setstrillega(json, k,v):
json[k] = str(v) + ',*&#%()='[random.randint(1, 8) - 1] + 'H1 \u266a@\u5c0f\u8776\u6c42\u5b88\u62a4'
list = { 'del': lambda: delkey(json,k),
...
'none': lambda: set(json,k,None),
'0': lambda: set(json,k,0),
'-1': lambda: set(json,k,-1),
'maxlong': lambda: set(json, k, 9223372036854775808),
'*n': lambda: setintmultin(json, k,kv),
'cut': lambda: setstrshorten(json, k, kv),
'overlen': lambda: setstroverlen(json, k, kv),
'illega': lambda: setstrillega(json, k, kv),
...
}
return list[type]()
python proxy.py -a /api/user/get -k errno=1 劫持 api 为/api/user/get,原 response 中 errnor 字段修改为 1
python proxy.py -a /api/user/get -k re:name="H1 \u266a@\u5c0f\u8776\u6c42\u5b88\u62a4" 正则索引含 name 的修改为带乱码符号字符串
python proxy.py -r 1 清空 mockserver 中配置
python proxy.py -d 2g 模拟延迟 2g 网络
python proxy.py -b {} 返回空 body
python proxy.py -b {xxx{'' 返回非 json 格式 body
python proxy.py -a /api/user/get -k re:name=fun:del 模糊查找 name 关键字,将其键删除
python proxy.py -a /api/user/get -k data.uid=fun:maxint path 查找 data 节点下 uid 关键字 ,修改为溢出的 int
是不是很容易理解
考虑后续与思寒的 appcrawler 做插件对接,做自动遍历的 mock 测试
https://github.com/zhangzhao4444/Apimock
如有 bug 和好想法可及时联系我