接口请求体(文件)
文件上传接口场景
- Content-Type 类型
- 上传文件
- 创建本地文件
- 调用方法
- multiPart()
- 参数:String name
- 参数:File file
@Test
void header(){
// 需要上传的文件对象
File myFile = new File("src/test/resources/hogwarts.txt");
// 忽略HTTPS校验
RestAssured.useRelaxedHTTPSValidation();
given()
.multiPart("hogwarts", myFile) // 传递文件对象
.log().all()
.when()
.post("https://httpbin.ceshiren.com/post") //发送POST请求
.then()
.log().all()
.statusCode(200); // 响应断言
}
@Test
void testUploadFiles(){
// 需要上传的文件对象
File myFile = new File("src/test/resources/hogwarts.txt");
// 定义一个代理的配置信息
RestAssured.proxy = host("localhost").withPort(8888);
// 忽略HTTPS校验
RestAssured.useRelaxedHTTPSValidation();
given()
.multiPart("hogwarts", myFile) // 传递文件对象
.multiPart("ceshiren", "{\"hogwarts\": 666}",
"application/json") // 传递JSON数据
.log().headers() // 打印请求消息头
.log().body() // 打印请求消息体
.when()
.post("https://httpbin.ceshiren.com/post") // 发送POST请求
.then()
.statusCode(200); // 响应断言
}
接口请求体(from表单)
- Content-Type 类型
- application/x-www-form-urlencoded
- 应用场景
- form表单请求的使用
@Test
void testFormParam() {
// 忽略HTTPS校验
RestAssured.useRelaxedHTTPSValidation();
// 发送 POST 请求
given()
.formParam("username", "hogwarts") // 添加表单数据
.log().all()
.when()
.post("https://httpbin.ceshiren.com/post") // 发送请求
.then()
.log().all()
.statusCode(200); // 响应断言
}
@Test
void testFormParams() {
// 忽略HTTPS校验
RestAssured.useRelaxedHTTPSValidation();
// 发送 POST 请求
given()
.formParams("username", "hogwarts",
"pwd", "666") // 添加表单数据
.log().all()
.when()
.post("https://httpbin.ceshiren.com/post") // 发送请求
.then()
.log().all()
.statusCode(200); // 响应断言
}
接口请求体(XML)
- 简介
- 是 eXtensible Markup Language 的缩写
- 是 可扩展标记语言,类似 HTML
- 是用来传输和存储数据
- 是通过 < > 标签来描述信息
- 是 W3C 的推荐标准
- 请求
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
<scope>test</scope>
</dependency>
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Body>
<Add xmlns="http://tempuri.org/">
<intA>1</intA>
<intB>1</intB>
</Add>
</Body>
</Envelope>
@Test
void testSoapApi() throws IOException {
// 定义请求体数据:源自文件对象
File file = new File("src/test/resources/add.xml");
FileInputStream fis = new FileInputStream(file);
String reqBody = IOUtils.toString(fis, "UTF-8");
given()
.contentType("text/xml") // 定制请求内容媒体类型
.body(reqBody) // 定制请求体数据
.log().headers() // 打印请求头信息
.log().body() // 打印请求体信息
.when()
.post("http://dneonline.com//calculator.asmx") // 发送请求
.then()
.log().all()
.statusCode(200); // 响应状态码断言
}
接口响应断言(XML)
- XPath 基本语法
- 简介
- 是 XML 路径语言
- 是 XML Path Language 的缩写
- 是用来确定 XML 文档中某部分位置
- 语法
Xpath |
描述 |
/ |
根节点 |
. |
现行节点 |
// |
不管位置,选择所有符合条件的元素 |
* |
匹配所有元素节点 |
|
迭代器标示 |
| |
支持迭代器中做多选 |
@Test
void testXML() throws IOException {
// 定义请求体数据:源自文件对象
File file = new File("src/test/resources/add.xml");
FileInputStream fis = new FileInputStream(file);
String reqBody = IOUtils.toString(fis, "UTF-8");
given()
.contentType("text/xml") // 定制请求内容媒体类型
.body(reqBody) // 定制请求体数据
.when()
.post("http://dneonline.com/calculator.asmx") // 发送请求
.then()
.log().body() // 打印响应体信息
.body("//AddResult.text()", equalTo("2")); // 响应断言
}
cookie处理
- HTTP Headers
- 简介
- HTTP Headers 也叫做 HTTP 消息头
- 允许客户端和服务器传递附加信息
- 由名称、冒号、具体的值组成
- 设置请求Headers
@Test
void testSetHeader() {
given()
.header("User-Agent", "hogwarts") // 设置请求头
.relaxedHTTPSValidation() // 忽略HTTPS校验
.when()
.get("https://httpbin.ceshiren.com/get") // 发送请求
.then()
.log().all() // 打印完整响应信息
.statusCode(200); // 响应断言
}
- HTTP Cookie
- Cookie 使用场景
- 添加 Cookie 的两种方式
@Test
void testAddCookieByHeader() {
// 通过header()方法设置Cookie
given()
.header("Cookie", "my_cookie1=hogwarts") // 设置Cookie
.relaxedHTTPSValidation() // 忽略HTTPS校验
.when()
.get("https://httpbin.ceshiren.com/get") // 发送请求
.then()
.log().all() // 打印完整响应信息
.statusCode(200); // 响应断言
}
@Test
void testAddCookie() {
// 添加单个Cookie
given()
.cookie("my_cookie", "hogwarts") // 设置Cookie
.relaxedHTTPSValidation() // 忽略HTTPS校验
.when()
.get("https://httpbin.ceshiren.com/get") // 发送请求
.then()
.log().all() // 打印完整响应信息
.statusCode(200); // 响应断言
}
超时处理
- 设置超时时间
- 步骤
- 创建 HttpClientConfig 实例
- 创建 RestAssuredConfig 实例
- given 语句中调用 config() 方法
public class RestAssuredTest {
@BeforeAll
static void setupClass(){
RestAssured.baseURI = "https://httpbin.ceshiren.com";
// 忽略HTTPS校验
RestAssured.useRelaxedHTTPSValidation();
}
@Test
void case1() {
given()
.when()
.get("/get") // 发送GET请求
.then()
.statusCode(200); // 响应断言
}
@Test
void case2(){
// 自定义HttpClientConfig对象
// 设置响应超时时长为3秒,单位是毫秒
HttpClientConfig clientConfig = HttpClientConfig
.httpClientConfig()
.setParam("https.socket.timeout", 3000);
// 定义RestAssuredConfig对象
// 传入自定义的HttpClientConfig对象
RestAssuredConfig myTimeout = RestAssuredConfig
.config()
.httpClient(clientConfig);
// 接口调用
given()
.config(myTimeout) // 设置超时处理
.when()
.get("/delay/10") // 特定接口,延迟10秒响应
.then()
.statusCode(200); // 响应断言
}
@Test
void case3(){
given()
.when()
.get("/get") // 发送GET请求
.then()
.statusCode(200); // 响应断言
}
}
代理配置
- 简介
- 介于客户端与服务器之间
- 可以监听请求和响应信息
- 充当防火墙和 Web 过滤器
- 对比
- RESTassured使用代理
- 开启代理工具监听请求
- 配置代理
- 局部:通过proxy()方法
@Test
void testHTTPProxy() {
given()
.proxy(8888) // 设置代理
.when()
.get("http://httpbin.org/get") // 发送 HTTP请求
.then()
.log().all() // 打印完整响应信息
.statusCode(200); // 响应断言
}
@Test
void testHTTPProxy1() {
// 定义一个代理的配置信息
RestAssured.proxy = host("localhost").withPort(8888);
given()
.relaxedHTTPSValidation() // 忽略HTTPS校验
.when()
.get("https://httpbin.ceshiren.com/get")
.then()
.log().all() // 打印完整响应信息
.statusCode(200); // 响应断言
}
多层嵌套响应断言
多层嵌套结构
// - 层级多。
// - 嵌套关系复杂。
{
"errcode": 0,
"errmsg": "ok",
"userid": "zhangsan",
"name": "张三",
"department": [1, 2],
"order": [1, 2],
"position": "后台工程师",
"mobile": "13800000000",
"gender": "1",
"email": "zhangsan@gzdev.com",
"biz_mail": "zhangsan@qyycs2.wecom.work",
"is_leader_in_dept": [1, 0],
"direct_leader": ["lisi", "wangwu"],
"avatar": "http://wx.qlogo.cn/mmopen/ajNVdqHZLLA3WJ6DSZUfiakYe37PKnQhBIeOQBO4czqrnZDS79FH5Wm5m4X69TBicnHFlhiafvDwklOpZeXYQQ2icg/0",
"thumb_avatar": "http://wx.qlogo.cn/mmopen/ajNVdqHZLLA3WJ6DSZUfiakYe37PKnQhBIeOQBO4czqrnZDS79FH5Wm5m4X69TBicnHFlhiafvDwklOpZeXYQQ2icg/100",
"telephone": "020-123456",
"alias": "jackzhang",
"address": "广州市海珠区新港中路",
"open_userid": "xxxxxx",
"main_department": 1,
"extattr": {
"attrs": [
{
"type": 0,
"name": "文本名称",
"text": {
"value": "文本"
}
},
{
"type": 1,
"name": "网页名称",
"web": {
"url": "http://www.test.com",
"title": "标题"
}
}
]
},
"status": 1,
"qr_code": "https://open.work.weixin.qq.com/wwopen/userQRCode?vcode=xxx",
"external_position": "产品经理",
"external_profile": {
"external_corp_name": "企业简称",
"wechat_channels": {
"nickname": "视频号名称",
"status": 1
},
"external_attr": [
{
"type": 0,
"name": "文本名称",
"text": {
"value": "文本"
}
},
{
"type": 1,
"name": "网页名称",
"web": {
"url": "http://www.test.com",
"title": "标题"
}
},
{
"type": 2,
"name": "测试app",
"miniprogram": {
"appid": "wx8bd80126147dFAKE",
"pagepath": "/index",
"title": "my miniprogram"
}
}
]
}
}
- JSONPath
- 简介
- 在 JSON 数据中定位和提取特定信息的查询语言。
- JSONPath 使用类似于 XPath 的语法,使用路径表达式从 JSON 数据中选择和提取数据。
- 相比于传统的提取方式,更加灵活,并且支持定制化。
- 对比
场景 |
对应实现 |
JSONPath实现 |
提取 errcode 对应的值 |
res[“errcode”] |
$.errcode |
提取 title 对应的值 |
res[“extattr”][“external_profile”][“external_attr”][1][“web”][“title”] 等 |
$…title |
提取 type 为 0 的 name |
编码实现 |
$…external_attr[?(@.type==0)].name |
提取 attrs 下的所有的 name |
编码实现 |
$…attrs…name |
符号 |
描述 |
$ |
查询的根节点对象,用于表示一个 json 数据,可以是数组或对象 |
@ |
过滤器(filter predicate)处理的当前节点对象 |
* |
通配符 |
. |
获取子节点 |
… |
递归搜索,筛选所有符合条件的节点 |
?() |
过滤器表达式,筛选操作 |
[start:end] |
数组片段,区间为[start,end),不包含 end |
[A]或[A,B] |
迭代器下标,表示一个或多个数组下标 |
<!-- 相关依赖 -->
<properties>
<json-path.version>2.8.0</json-path.version>
</properties>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>${json-path.version}</version>
</dependency>
@Test
void jsonpathRes(){
String jsonData = "{\"username\":\"hogwarts\",\"password\":\"test12345\",\"code\":\"\"}";
String res = given()
.body(jsonData)
.when()
.post("https://httpbin.hogwarts.ceshiren.com/post")
.then()
.extract().response().getBody().asString();
// 第一种获取方式
DocumentContext context = JsonPath.parse(res);
ArrayList<String> codeList = context.read("$..code");
// 第二种获取方式
// ArrayList<String> codeList2 = JsonPath.read(res, "$..code");
}