一、前言
1. API接口响应的JSON格式文本
一般而言,API接口的响应普遍是一个JSON格式文本。而一部分接口不止返回1条数据,而会返回复数数据。
举个例子,有这么个接口。根据status去查询用户email,返回结果不止一个用户。大致结构如下。
{
"errCode": "0",
"data": [{
"Id": 1,
"Email": "[email protected]"
}, {
"Id": 2,
"Email": "[email protected]}"
},
...
...
...
{
"Id": 9,
"Email": "[email protected]}"
}]
}
我们发现,最外层是{"errcode":0,"data":[...]},而data层的数据是可以通过数据库查询结果进行验证的。
2. JDBC返回的ArrayList对象
Jmeter中使用JDBC处理器去执行select语句后,在监听器里看到的查询结果是这样的表格形式。
id | |
---|---|
1 | [email protected] |
2 | [email protected] |
其实JDBC还会返回一个ArrayList对象。ArrayList内部是一个HashMap键值对,列名是key,数据是value。
根据上面示例中的查询结果,大概是这样的[{id=1, email="[email protected]"},{id=2,email="[email protected]"}]
//使用方法
ArrayList list = vars.getObject("sqlResult"); //JDBC处理器中申明的变量名
list.size() == 2
list.get(0) == {id=1, email="[email protected]"}
((HashMap)list.get(0)).get("email") == "[email protected]"
3. 转化思路
Data层JSON思路大致如下:
1. 写一个方法,传入name和value,返回"name": value(或者"name":"value")
2. 创建一个临时List,用来装属性。循环拼接成"name1":value1,"name2":"value2",..."name9":"value9"
3. 根据JDBC返回的List,循环拼接成复数数据{"id":1,"email":"[email protected]"},{"id":2,"email":"[email protected]"}
4. 演示接口示例
二、取数据库
1. 编写sql,取出Data部分中我们需的Id和Email值。要注意我们接口请求参数中有一个status,写在where条件里。
这里要注意 1. as 别名与接口响应中名称一致、2.注意排序
2. 添加一个JDBC后置处理器,将sql填入。并且在Result variable name文本框中填一个变量名,用来接收ArrayList对象
3. 这时Debug Sampler里可以看到这个ArrayList对象了。
三、转化结果
1. 添加一个BeanShell后置处理器,填入以下脚本内容
getParams() 用来手动转化成"name":int 或"name":"string"格式。用于嵌套json,譬如children:[另一个完整的json]。
getParamsByList() 用来自动转化,前提是你的sql返回的列名与属性名一致。
*这2个方法嫌放在beanshell里太丑,可以自己写个jar包来用。实际工作中不用变动方法内部!
import java.util.ArrayList;
import java.util.HashMap;
//手动传入value
static String getParams(String name, String value, boolean isString) {
name = "\"" + name + "\"";
if(isString) {
value = "\"" + value + "\"";
}
return name + ":" + value;
}
//自动根据name去ArrayList取值
static String getParamsByList(ArrayList list, String name, int i, boolean isString){
String value = "";
if (((HashMap)list.get(i)).get(name.toLowerCase()) != null){
value = ((HashMap)list.get(i)).get(name.toLowerCase()).toString();
}else{
value = "null";
return getParams(name, value, false);
}
return getParams(name, value, isString);
}
//第一步 指定JDBC返回值
ArrayList list = vars.getObject("User_sqlResult");
//第二步 传入参数名
String result = "";
for(int i = 0; i < list.size(); i++) {
ArrayList tmpList = new ArrayList();
tmpList.add(getParamsByList(list, "Id", i, false));
tmpList.add(getParamsByList(list, "Email", i, true));
String tmp = "";
for (int l = 0; l < tmpList.size(); l++) {
tmp += tmpList.get(l);
if (l < tmpList.size()-1) { tmp += ","; }
}
result += "{" + tmp + "}";
if (i < list.size()-1){ result += ","; }
}
//System.out.println(result);
//第三步 拼接首尾
result = bsh.args[0] + result + bsh.args[1] + "\n";
//System.out.println(result);
vars.put("Assertion", result);
2. 在下方填入JDBC里取出来的ArrayList变量名 和 add一下属性就能拼接成JSON格式,几十个参数都可以。
我们利用list特性把属性一个个add进去后,根据size()的长度 循环拼接单条数据
{"Id":-1,"Email":"[email protected]"}
再根据数据库取出来的list的长度,拼接完整数据列表
{"Id":-1,"Email":"[email protected]"},{"Id":202,"Email":null},{"Id":203,"Email":null},{"Id":204,"Email":null},{"Id":205,"Email":null},{"Id":588,"Email":null},{"Id":1443,"Email":"[email protected]"},{"Id":1444,"Email":"[email protected]"},{"Id":1445,"Email":"[email protected]"},{"Id":1446,"Email":"[email protected]"}
3. 目前还缺少{"errCode":"0","data":[ 和 ]} 把这个json框起来,在这一步中补全。
四、断言
1.我习惯把所有接口都取出Assertion,再放到BeanShell断言里检查。
(你也可以把取出来的Assertion放在普通的响应断言中去断言)
//断言
String Assertion = vars.get("Assertion");
String ResponseResult = prev.getResponseDataAsString();
//判断断言是否通过
if(ResponseResult.equals(Assertion)){
Failure = false;
}else{
Failure = true;
FailureMessage = "接口响应:\r\n" + ResponseResult + "\r\n";
FailureMessage += "用例断言:\r\n" + Assertion;
String logInfo = "\n";
logInfo = logInfo + prev.getThreadName() + " " + prev.getSampleLabel() + "\n";
logInfo = logInfo + prev.getSamplerData() + "\n";
logInfo = logInfo + prev.getResponseCode() + "\n\n";
logInfo = logInfo + prev.getResponseDataAsString() + "\n";
log.info(logInfo);
}
2.如果API响应结果有问题,效果是这样的