【Java】RestAssured
静态方法导入
提高使用 rest-assured 的效率:
Java io.restassured.RestAssured. io.restassured.matcher.RestAssuredMatchers. org.hamcrest.Matchers.* |
---|
使用Json Schema validation:Json Schema简介
Java io.restassured.module.jsv.JsonSchemaValidator.* |
---|
使用spring-mock-mvc 模型的 Rest Assured DSL 来对 Spring 的 controller 层进行单元测试
Java io.restassured.module.mockmvc.RestAssuredMockMvc.* |
---|
示例:
例一 - JSON
某个 get 请求 (to http://localhost:8080/lotto) 返回 JSON 如下:
JSON { “lotto”:{ “lottoId”:5, “winning-numbers”:[2,45,34,23,7,5,3], “winners”:[ { “winnerId”:23, “numbers”:[2,45,34,23,3,5] }, { “winnerId”:54, “numbers”:[52,3,12,11,18,22] }] } } |
---|
REST assured 可以轻松地进行 get 请求并对响应信息进行处理。举个例子:
| Java
// 请求/lotto接口,然后判断返回的lottoId的值是否等于 5
get(“/lotto”).then().body(“lotto.lottoId”, equalTo(5));
// 检查winnerId的取值包括23或54
get(“/lotto”).then().body(“lotto.winners.winnerId”, hasItems(23, 54));
// 验证price字段是否等于float类型的12.12
get(“/price”).then().body(“price”, is(12.12f));
// 验证price字段是否等于BigDecimal类型的12.12
given().
config(RestAssured.config().jsonConfig(jsonConfig().numberReturnType(BIG_DECIMAL))).
when().
get(“/price”).
then().
body(“price”, is(new BigDecimal(12.12)); |
| —- |
注意:这里的 JsonPath 语法使用的是Groovy 的 GPath标注法。
JSON Schema validation
在类路径中放置以下的 schema 文件(idea 的话可以放在 resources 目录下),
products-schema.json:
JSON { “$schema”: “http://json-schema.org/draft-04/schema#“, “title”: “Product set”, “type”: “array”, “items”: { “title”: “Product”, “type”: “object”, “properties”: { “id”: { “description”: “The unique identifier for a product”, “type”: “number” }, “name”: { “type”: “string” }, “price”: { “type”: “number”, “minimum”: 0, “exclusiveMinimum”: true }, “tags”: { “type”: “array”, “items”: { “type”: “string” }, “minItems”: 1, “uniqueItems”: true }, “dimensions”: { “type”: “object”, “properties”: { “length”: {“type”: “number”}, “width”: {“type”: “number”}, “height”: {“type”: “number”} }, “required”: [“length”, “width”, “height”] }, “warehouseLocation”: { “description”: “Coordinates of the warehouse with the product”, “$ref”: “http://json-schema.org/geo“ } }, “required”: [“id”, “name”, “price”] } } |
---|
使用上面的schema文件,验证 /products 接口返回的数据是否符合规范
Java get(“/products”).then().assertThat().body(matchesJsonSchemaInClasspath(“products-schema.json”)); |
---|
使用io.restassured.module.jsv.JsonSchemaValidator前,需要添加依赖包:
XML |
---|
JSON Schema Validation 设置项
rest-assured 的json-schema-validator 模块使用 Francis Galiegue 的json-schema-validator (fge) 库来进行验证。
| Java
// 设置用于schema验证的库
JsonSchemaFactory jsonSchemaFactory = JsonSchemaFactory.newBuilder().setValidationConfiguration(ValidationConfiguration.newBuilder().setDefaultVersion(DRAFTV4).freeze()).freeze();
// 发起请求并用设置的库进行schema验证
get(“/products”).then().assertThat().body(matchesJsonSchemaInClasspath(“products-schema.json”).using(jsonSchemaFactory)); |
| —- |
Java // using方法,默认是进行验证的,可设置checkedValidation=false不进行验证 get(“/products”).then().assertThat().body(matchesJsonSchemaInClasspath(“products-schema.json”).using(settings().with().checkedValidation(false))); |
---|
Json Schema Validation 的静态配置
Java JsonSchemaValidator.settings = settings().with().jsonSchemaFactory( JsonSchemaFactory.newBuilder().setValidationConfiguration(ValidationConfiguration.newBuilder().setDefaultVersion(DRAFTV3).freeze()).freeze()). and().with().checkedValidation(false); get(“/products”).then().assertThat().body(matchesJsonSchemaInClasspath(“products-schema.json”)); |
---|
任意一个由JsonSchemaValidator导入的matcher都会默认使用DRAFTV3库,且不进行验证。
想要重置JsonSchemaValidator的默认设置只要调用reset方法就可以了:
Java JsonSchemaValidator.reset(); |
---|
不使用 rest-assured 的 Json Schema Validation
不依赖 rest-assured 的情况下使用json-schema-validator模块
| Java
import org.junit.Test;
import static io.restassured.module.jsv.JsonSchemaValidator.matchesJsonSchemaInClasspath;
import static org.hamcrest.MatcherAssert.assertThat;
public class JsonSchemaValidatorWithoutRestAssuredTest {
@Test <br /> public void validates_schema_in_classpath() {<br /> _// 定义json_<br /> String json = ... _// Greeting response_
_// 验证json是否符合schema的定义_<br /> assertThat(json, matchesJsonSchemaInClasspath("greeting-schema.json"));<br /> }<br />} |
| —- |
匿名式的 JSON 根节点验证
一个匿名的 JSON 根属性可以通过使用$或者空字符串作为路径来识别。
Java // 比如需要验证 [1, 2, 3] 这个json when(). get(“/json”). then(). body(“$”, hasItems(1, 2, 3)); // An empty string “” would work as well |
---|
例二 - XML
XML 可以通过一种简单的方式解析。假设一个 POST 请求http://localhost:8080/greet,XML返回:
XML |
---|
在请求中返回了一个greeting 节点包含 firstname 和 lastname 2个参数的 。可以通过 rest-assured 轻松地解析和校验这个例子:
Java given(). parameters(“firstName”, “John”, “lastName”, “Doe”). when(). post(“/greetXML”). then(). // 校验greeting.firstName等于John body(“greeting.firstName”, equalTo(“John”)). |
---|
同时解析 firstname 和 lastname
Java given(). parameters(“firstName”, “John”, “lastName”, “Doe”). when(). post(“/greetXML”). then(). // 校验greeting.firstName等于John body(“greeting.firstName”, equalTo(“John”)). // 校验greeting.lastName等于Doe body(“greeting.lastName”, equalTo(“Doe”)); |
---|
或者
Java with().parameters(“firstName”, “John”, “lastName”, “Doe”).when().post(“/greetXML”).then().body(“greeting.firstName”, equalTo(“John”), “greeting.lastName”, equalTo(“Doe”)); |
---|
注:遵循 Groovy 的 GPath 语法
XML 命名空间
使用io.restassured.config.XmlConfig声明一个命名空间。举个例子,有一个位于http://localhost:8080的资源namespace-example,返回如下的 XML:
XML |
---|
可以声明http://localhost/这个 URI 并且验证其响应:
Java given(). config(RestAssured.config().xmlConfig(xmlConfig().declareNamespace(“test”, “http://localhost/“))). when(). get(“/namespace-example”). then(). body(“foo.bar.text()”, equalTo(“sudo make me a sandwich!”)). body(“:foo.:bar.text()”, equalTo(“sudo “)). body(“foo.test:bar.text()”, equalTo(“make me a sandwich!”)); |
---|
这个路径语法遵循 Groovy 的 XmlSlurper 语法。
XPath
使用 x-path 来解析 XML 响应
Java given().parameters(“firstName”, “John”, “lastName”, “Doe”).when().post(“/greetXML”).then().body(hasXPath(“/greeting/firstName”, containsString(“Jo”))); |
---|
或者
Java given().parameters(“firstName”, “John”, “lastName”, “Doe”).post(“/greetXML”).then().body(hasXPath(“/greeting/firstName[text()=’John’]”)); |
---|
在 XPath 表达式中使用命名空间,需要在配置中启用这些选项:
Java given(). config(RestAssured.config().xmlConfig(xmlConfig().with().namespaceAware(true))). when(). get(“/package-db-xml”). then(). body(hasXPath(“/db:package-database”, namespaceContext)); |
---|
namespaceContext 是javax.xml.namespace.NamespaceContext的一个实例 。
Schema 和 DTD
XML 响应体也可以通过一个 XML Schema (XSD) 或 DTD验证。
XSD 例子
Java get(“/carRecords”).then().assertThat().body(matchesXsd(xsd)); |
---|
DTD 例子
Java get(“/videos”).then().assertThat().body(matchesDtd(dtd)); |
---|
matchesXsd()和matchesDtd()在可以从io.restassured.matcher.RestAssuredMatchers导入。
例三 - 复杂的解析和验证
rest-assured 实现了 Groovy,它可以从 Groovy 集合的 API 的优点中获益。
Ruby def words = [‘ant’, ‘buffalo’, ‘cat’, ‘dinosaur’] def wordsWithSizeGreaterThanFour = words.findAll { it.length() > 4 } |
---|
在第一行,简单地定义了一个包含一些单词的列表,第二行检索了列表里的所有长度大于 4 的单词。通过一个叫做 findAll 的 Groovy 闭包,闭包有一个内部变量it,代表着当前words中的元素,查找words列表中所有长度大于4的元素。所以新的列表 wordsWithSizeGreaterThanFour,包含buffalo和dinosaur。
这里还有一些其它的有趣的方法,我们也可以使用在 Groovy 集合中:
find – 找到第一个匹配闭包谓词(closure predicate)的元素
collect – 收集在集合里的每个元素都调用的闭包返回值(collect the return value of calling a closure on each item in a collection)
sum – 对集合里的元素进行求和
max/min – 返回集合里的最大值/最小值
如何在使用 rest-assured 验证 XML 和 JSON 响应时利用这些优点?
XML 示例
比如有个资源http://localhost:8080/shopping返回如下的 XML:
XML |
---|
写一个测试用例来检验类型为 groceries 的 category 节点有 Chocolate 和 Coffee 这两个项目。
Java when(). get(“/shopping”). then(). body(“shopping.category.find { it.@type == ‘groceries’ }.item”, hasItems(“Chocolate”, “Coffee”)); |
---|
使用 XML 路径shopping.category获取了所有 categoriy 的一个列表。在这个列表中又调用了一个方法,find,来返回有type这个属性且该属性值为groceries的单个 category 节点。在这个 category 上继续收集所有相关联的项目(item)。由于这里与 category 相关联的项目不止一个,所以会返回一个列表。接下来通过 Hamcrest matcher 的hasItems方法来解析它。
但是如果想取得一些项目(item)但又不想进行断言验证该怎么办?您可以参考XmlPath:
Java // Get the response body as a String String response = get(“/shopping”).asString(); // And get the groceries from the response. “from” is statically imported from the XmlPath class List |
---|
如果 groceries 是您对这个响应里唯一的关注点,也可以使用一个捷径:
Java // Get the response body as a String List |
---|
深度优先搜索
实际上之前的例子还可以继续简化:
Java when(). get(“/shopping”). then(). body(“**.find { it.@type == ‘groceries’ }”, hasItems(“Chocolate”, “Coffee”)); |
---|
是一种在 XML 文件中做深度优先搜索的捷径。
搜索第一个type属性值等于”groceries”的节点。注意,没有在”item”这个 XML 路径结束。原因是在 category 节点返回一个列表的项目值时,自动调用了toString()这个方法。
JSON 示例**
假设http://localhost:8080/store返回如下的 JSON:
JSON { “store”:{ “book”:[ { “author”:”Nigel Rees”, “category”:”reference”, “price”:8.95, “title”:”Sayings of the Century” }, { “author”:”Evelyn Waugh”, “category”:”fiction”, “price”:12.99, “title”:”Sword of Honour” }, { “author”:”Herman Melville”, “category”:”fiction”, “isbn”:”0-553-21311-3”, “price”:8.99, “title”:”Moby Dick” }, { “author”:”J. R. R. Tolkien”, “category”:”fiction”, “isbn”:”0-395-19395-8”, “price”:22.99, “title”:”The Lord of the Rings” } ] } } |
---|
例 1
发起一个请求”/store”,并且做了一个断言:搜集满足 price 字段值小于 10 的所有 book 数组里的 title 字段,得到了”Sayings of the Century”和”Moby Dick”这两个结果:
Java when(). get(“/store”). then(). body(“store.book.findAll { it.price < 10 }.title”, hasItems(“Sayings of the Century”, “Moby Dick”)); |
---|
就像上面 XML 的例子,使用闭包获取所有 price 字段值低于 10 的 book 数组,并且返回相应的 title 字段值集合。
然后使用hasItems这个匹配器来断言得到的预期结果。使用JsonPath 可以用下面的方法替代:
Java // Get the response body as a String String response = get(“/store”).asString(); // And get all books with price < 10 from the response. “from” is statically imported from the JsonPath class List |
---|
例 2
如何断言所有 author 字段值长度总和是否大于 50 的结果。
这是个挺难以回答的问题,也正展示了闭包和 Groovy 集合的强大之处。
Java when(). get(“/store”); then(). body(“store.book.author.collect { it.length() }.sum()”, greaterThan(50)); |
---|
首先通过 (store.book.author) 得到了所有的 author 字段值,然后使用闭包里的方法{ it.length() }解析这个集合。它所做的是对列表里的每一个 author 字段执行一次length()方法,然后返回一个新的列表。在这个列表中,再调用sum()方法来求得字符长度的总和。
最终的结果是 53,并且我们使用greaterThan匹配器的断言结果是大于 50 。
但是实际上可以继续简化这种写法。可以再次参考”words”这个例子
JavaScript def words = [‘ant’, ‘buffalo’, ‘cat’, ‘dinosaur’] |
---|
Groovy 有一个便利的方法可以遍历列表中的所有元素,使用*来调用。举个例子:
JavaScript def words = [‘ant’, ‘buffalo’, ‘cat’, ‘dinosaur’] assert [3, 6, 3, 8] == words*.length() |
---|
Groovy 返回了一个新的包含 words 中每个字段字符长度的列表。也可以把 rest-assured 中的这个语法用在 author 列表中:
Java when(). get(“/store”); then(). body(“store.book.author*.length().sum()”, greaterThan(50)). |
---|
当然也可以使用JsonPath来获取这个结果:
Java // Get the response body as a string String response = get(“/store”).asString(); // Get the sum of all author length’s as an int. “from” is again statically imported from the JsonPath class int sumOfAllAuthorLengths = from(response).getInt(“store.book.author*.length().sum()”); // We can also assert that the sum is equal to 53 as expected. assertThat(sumOfAllAuthorLengths, is(53)); |
---|
其它例子
Micha Kops 曾写过一篇很优秀的博客,里面包含大量示例(包括可检出的代码)。您可以由此进入试读。
Bas Dijkstra也开展过不少关于 rest-assured 的开源研究和资源。你可以由此进入试读,如果您想试用或者作出贡献,他的 github 仓库里有些可以尝试的练习题。
关于 float 和 double
浮点型数字必须和 Java 的基本类型”float”区分开。举个例子,如果看下面的 JSON 对象:
JSON { “price”:12.12 } |
---|
如下的测试将会失败,因为是在拿一个”double”在比较,而不是”float”:
Java get(“/price”).then().assertThat().body(“price”, equalTo(12.12)); |
---|
想用”float”比较的话写法应该是:
Java get(“/price”).then().assertThat().body(“price”, equalTo(12.12f)); |
---|
语法关注点
当阅读 rest-assured 的博客时,会看到许多使用”given / expect / when”语法的例子,举个例子:
Java given(). param(“x”, “y”). expect(). body(“lotto.lottoId”, equalTo(5)). when(). get(“/lotto”); |
---|
这是一种 “遗留语法”,这实际上是 rest-assured 1.x.版本用来写测试用例的方式。然而这种运作方式令许多用户迷惑甚至恼怒。这是因为一开始没有把”given / when / then”作为主要的技术来使用。所以 rest-assured 的 2.0 版本之前差不多是这种类似 BDD-like 测试的标准用法。”given / expect /when”在 2.0 仍然可用,但是”given / when / then”可读性更强所以在测试用例中更为推荐。使用”given /expect / when”还有一个好处,就是所有期望中的错误可以在同时展示出来,这是新语法做不到的。这意味着如果你有多个预期结果想要检验你可以:
Java given(). param(“x”, “y”). expect(). statusCode(400). body(“lotto.lottoId”, equalTo(6)). when(). get(“/lotto”); |
---|
rest-assured 将同时报告状态码预期和响应体预期结果都是错的。将这些用新语法重写:
Java given(). param(“x”, “y”). when(). get(“/lotto”). then(). statusCode(400). body(“lotto.lottoId”, equalTo(6)); |
---|
仅仅报告首个预期/断言失败的内容(比如预期状态码是 400 实际是 200),第二个断言将不执行。您将不得不重新运行这个用例以期获取到第二个断言的结果。
语法糖
rest-assured 中另一件值得注意的是,有些语法仅仅存在于语法糖中,举个例子,”and”在一行代码中使用可以增强可读性。
Java given().param(“x”, “y”).and().header(“z”, “w”).when().get(“/something”).then().assertThat().statusCode(200).and().body(“x.y”, equalTo(“z”)); |
---|
等价于:
Java given(). param(“x”, “y”). header(“z”, “w”). when(). get(“/something”). then(). statusCode(200). body(“x.y”, equalTo(“z”)); |
---|
获得响应体信息
获得响应的内容。比方说你想通过发起一个 get 请求”/lotto”并获取其响应内容。你可以以多种方式:
Java InputStream stream = get(“/lotto”).asInputStream(); // Don’t forget to close this one when you’re done byte[] byteArray = get(“/lotto”).asByteArray(); String json = get(“/lotto”).asString(); |
---|
从已验证的响应体中提取值
可以从响应信息中提取值,或者使用extract方法仅仅返回 response 本身的一个实例。如果想获取响应里的值,并将其作为接下来的请求内容,这会很有用。下面是一个叫做title的资源返回的 JSON 数据:
JSON { “title” : “My Title”, “_links”: { “self”: { “href”: “/title” }, “next”: { “href”: “/title?page=2” } } } |
---|
想验证内容类型是 JSON 格式且标题是My Title,但是还想要从中提取 next 的值并用来发起请求,下面是使用方法:
Java String nextTitleLink = given(). param(“param_name”, “param_value”). when(). get(“/title”). then(). contentType(JSON). body(“title”, equalTo(“My Title”)). extract(). path(“_links.next.href”); get(nextTitleLink). .. |
---|
如果您想提取多个值,也可以考虑返回整个响应体:
Java Response response = given(). param(“param_name”, “param_value”). when(). get(“/title”). then(). contentType(JSON). body(“title”, equalTo(“My Title”)). extract(). response(); String nextTitleLink = response.path(“_links.next.href”); String headerValue = response.header(“headerName”); |
---|
JSON (使用 JsonPath)
一旦我们取得了响应体,可以使用JsonPath来提取相应的数据:
Java int lottoId = from(json).getInt(“lotto.lottoId”); List |
---|
或者更高效一些:
Java JsonPath jsonPath = new JsonPath(json).setRoot(“lotto”); int lottoId = jsonPath.getInt(“lottoId”); List |
---|
注意这里我们独立地使用了JsonPath,而没有依赖 rest-assured 本身的功能,看getting started guide 获取更多信息。
JsonPath 配置
可以为 JsonPath 配置反序列化对象(object de-serializers),举个例子:
Java JsonPath jsonPath = new JsonPath(SOME_JSON).using(new JsonPathConfig(“UTF-8”)); |
---|
也可以静态配置好 JsonPath,这样所有的 JsonPath 实例都会共享这个配置:
Java JsonPath.config = new JsonPathConfig(“UTF-8”); |
---|
更多 JsonPath 的内容参照这篇博客。
注意:这里的 JsonPath 基于Groovy 的 GPath,不要和Jayway的搞混了。
XML (使用 XmlPath)
配置 XmlPath 的对象反序列化器和字符编码,举个例子:
Java XmlPath xmlPath = new XmlPath(SOME_XML).using(new XmlPathConfig(“UTF-8”)); |
---|
也可以静态地配置 XmlPath,使得所有的实例都能共享这套配置:
Java XmlPath.config = new XmlPathConfig(“UTF-8”); |
---|
更多关于 XmlPath 的信息参阅这篇博客。
获取某个路径下的值
如只是想发起一个请求并返回一个路径下的值,可以使用一个捷径:
Java int lottoId = get(“/lotto”).path(“lotto.lottoid”); |
---|
rest-assured 会基于响应体的 content-type 自动决定是使用 JsonPath 还是 XmlPath。如果这个类型在 rest-assured 没有被定义,它将会自动到default parser中查找。你可以自行(代码指定)决定使用哪种,比如:
Java String firstName = post(“/greetXML?firstName=John&lastName=Doe”).andReturn().xmlPath().getString(“firstName”); |
---|
xmlPath, jsonPath和htmlPath都是可选项。
Headers, cookies, status 等
您也可以获取 header, cookie, 状态行,状态码:
Java Response response = get(“/lotto”); // 获取所有 headers 信息 Headers allHeaders = response.getHeaders(); // 获取单个 header 信息 String headerName = response.getHeader(“headerName”); // 获取所有 cookie 键值对 Map // 获取单个 cookie 信息 String cookieValue = response.getCookie(“cookieName”); // 获取状态行信息 String statusLine = response.getStatusLine(); // 获取状态码信息 int statusCode = response.getStatusCode(); |
---|
多个 header 和 cookie
header 和 cookie 可以包含同名的多个值。
多个 header
要获取 header 的所有值,您需要首先从Response对象中获取Headers 对象。您需要首先从 Response 对象中获取 Headers 对象。您可以使用 Headers.getValues()方法返回一个具有所有 header 值的 List 列表。
多个 cookie
要获取 cookie 的所有值,您需要首先从Response对象中获取Cookie对象。您可以使用 Cookie.getValues()方法获取所有值,该方法返回包含所有 Cookie 值的 List 列表。
详细的 Cookies 信息
如果您需要获取 Cookie 的路径或过期日期等详细信息,您需要从 REST Assured 获取一个detailed cookie。您可以使用Response.getDetailedCookie(java.lang.String) 方法获取单个 Cookie,包括与给定名称相关联的所有属性。
您还可以使用Response.getDetailedCookies()方法获取所有详细的响应cookies。
指定请求数据
除了指定请求参数,您还可以指定 header,Cookie,正文和 Content Type。
请求 HTTP 资源
通常通过调用request specification中的 “HTTP 方法” 执行请求。例如:
Java when().get(“/x”). ..; |
---|
其中get是 HTTP 请求方法。
从 REST Assured 3.0.0 开始,您可以通过使用该方法为请求使用任何 HTTP 动词。
Java when(). request(“CONNECT”, “/somewhere”). then(). statusCode(200); |
---|
这将向服务器发送 “连接” 请求。
参数化
通常您可以这样指定参数:
Java given(). param(“param1”, “value1”). param(“param2”, “value2”). when(). get(“/something”); |
---|
REST Assured 将自动尝试基于 HTTP 方法确定哪个参数类型(即查询或表单参数)。在 GET 的情况下,查询参数将被自动使用,在 POST 的情况下将使用表单参数。在某些情况下,重要的是在 PUT 或 POST 中分离表单和查询参数。你可以这样使用:
Java given(). formParam(“formParamName”, “value1”). queryParam(“queryParamName”, “value2”). when(). post(“/something”); |
---|
参数也可以 url 上进行设置:
Java ..when().get(“/name?firstName=John&lastName=Doe”); |
---|
参数如果上传的是文件,字节数组,输入流或文本的可以参照Multi-part 类型的表单数据部分
多值参数
多值参数是每个参数名称具有多于一个值的参数(即,每个名称的值的列表)。您可以使用 var-args 指定这些值:
Java given().param(“myList”, “value1”, “value2”). .. |
---|
或者使用 list 列表:
Java List values.add(“value1”); values.add(“value2”); given().param(“myList”, values). .. |
---|
无值参数
您还可以指定一个没有值的请求或表单参数:
Java given().param(“paramName”). .. |
---|
路径参数
您还可以在请求中指定所谓的路径参数,例如
Java post(“/reserve/{hotelId}/{roomNumber}”, “My Hotel”, 23); |
---|
这些种类的路径参数在 REST Assured 中称为 “未命名路径参数”,因为它们是基于索引的(hotelId将等于 “My Hotel”,因为它是第一个占位符)。
您还可以使用命名路径参数:
| Java
given()
.pathParam(“hotelId”, “My Hotel”)
.pathParam(“roomNumber”, 23)
.when()
.post(“/reserve/{hotelId}/{roomNumber}”)
.then()
… | | —- |
路径参数使得更容易读取请求路径,且使请求路径能够在具有不同参数值的许多测试中容易地重复使用。
从版本 2.8.0 开始,您可以混合未赋值和赋值好的路径参数:
| Java
given()
.pathParam(“hotelId”, “My Hotel”)
.when()
.post(“/reserve/{hotelId}/{roomNumber}”, 23)
.then()
… | | —- |
这里 roomNumber 的值My Hotel将被替换为 23.
注意:指定太少或太多的参数将导致错误消息。对于高级用例,您可以从 [过滤器](#过滤器)添加,更改,删除(甚至冗余的路径参数)。
Cookie
通常模式下,您可以通过以下方法指定 Cookie:
Java given().cookie(“username”, “John”).when().get(“/cookie”).then().body(equalTo(“username”)); |
---|
也可以像这样给 cookie 指定多个值:
Java given().cookie(“cookieName”, “value1”, “value2”). .. |
---|
这将创建两个 cookie:cookieName = value1 和 cookieName = value2。
您还可以使用以下方式指定详细的 Cookie:
Java Cookie someCookie = new Cookie.Builder(“some_cookie”, “some_value”).setSecured(true).setComment(“some comment”).build(); given().cookie(someCookie).when().get(“/cookie”).then().assertThat().body(equalTo(“x”)); |
---|
或同时指定 cookies:
Java Cookie cookie1 = Cookie.Builder(“username”, “John”).setComment(“comment 1”).build(); Cookie cookie2 = Cookie.Builder(“token”, 1234).setComment(“comment 2”).build(); Cookies cookies = new Cookies(cookie1, cookie2); given().cookies(cookies).when().get(“/cookie”).then().body(equalTo(“username, token”)); |
---|
Header
Java given().header(“MyHeader”, “Something”).and(). .. given().headers(“MyHeader”, “Something”, “MyOtherHeader”, “SomethingElse”).and(). .. |
---|
也可以给一个 headers 指定多个值:
Java given().header(“headerName”, “value1”, “value2”). .. |
---|
这将创建两个 header,headerName = value1 和 headerName = value2
Header 合并/覆盖
默认情况下,header 合并可以这样:
Java given().header(“x”, “1”).header(“x”, “2”). .. |
---|
请求将包含两个标头,“x:1” 和 “x:2”。您可以在 [HeaderConfig](http://static.javadoc.io/io.rest-assured/rest-assured/3.0.1/io/restassured/config/HeaderConfig.html)的基础上进行更改。例如:
Java given(). config(RestAssuredConfig.config().headerConfig(headerConfig().overwriteHeadersWithName(“x”))). header(“x”, “1”). header(“x”, “2”). when(). get(“/something”). … |
---|
这意味着只有 header “x = 2” 被发送到服务器
Content Type
Java given().contentType(ContentType.TEXT). .. given().contentType(“application/json”). .. |
---|
请求正文
Java given().body(“some body”). .. // Works for POST, PUT and DELETE requests given().request().body(“some body”). .. // More explicit (optional) |
---|
Java given().body(new byte[]{42}). .. // Works for POST, PUT and DELETE given().request().body(new byte[]{42}). .. // More explicit (optional) |
---|
您还可以将 Java 对象序列化为 JSON 或 XML。点击这里了解详情。
验证响应数据
您还可以验证状态码,状态行,Cookie,headers,内容类型和正文。
响应体
请参阅使用示例,例如JSON 或 XML.
您还可以将响应正文映射到 Java 对象,单击这里 了解详细信息。
Cookie
Java get(“/x”).then().assertThat().cookie(“cookieName”, “cookieValue”). .. get(“/x”).then().assertThat().cookies(“cookieName1”, “cookieValue1”, “cookieName2”, “cookieValue2”). .. get(“/x”).then().assertThat().cookies(“cookieName1”, “cookieValue1”, “cookieName2”, containsString(“Value2”)). .. |
---|
状态码
Java get(“/x”).then().assertThat().statusCode(200). .. get(“/x”).then().assertThat().statusLine(“something”). .. get(“/x”).then().assertThat().statusLine(containsString(“some”)). .. |
---|
Header
Java get(“/x”).then().assertThat().header(“headerName”, “headerValue”). .. get(“/x”).then().assertThat().headers(“headerName1”, “headerValue1”, “headerName2”, “headerValue2”). .. get(“/x”).then().assertThat().headers(“headerName1”, “headerValue1”, “headerName2”, containsString(“Value2”)). .. |
---|
还可以在验证头时使用映射函数。 例如,假设您要验证header的 “Content-Length” 小于 1000。可以使用映射函数首先将头值转换为 int,然后在使用 Hamcrest 验证时使用 “整数” 匹配器:
Java get(“/something”).then().assertThat().header(“Content-Length”, Integer::parseInt, lessThan(1000)); |
---|
Content-Type
Java get(“/x”).then().assertThat().contentType(ContentType.JSON). .. |
---|
内容全匹配
Java get(“/x”).then().assertThat().body(equalTo(“something”)). .. |
---|
关联类型验证
您可以使用响应中的数据来验证响应的另一部分。 例如,从服务端返回的以下 JSON:
JSON { “userId” : “some-id”, “href” : “http://localhost:8080/some-id“ } |
---|
您可能会注意到,“href” 属性以 “userId” 属性的值结尾。 如果我们想验证这个,我们可以实现一个 io.restassured.matcher.ResponseAwareMatcher,可以:
Java get(“/x”).then().body(“href”, new ResponseAwareMatcher public Matcher<?> matcher(Response response) { return equalTo(“http://localhost:8080/“ + response.path(“userId”)); } }); |
---|
如果您使用 Java 8,你可以使用 lambda 表达式:
Java get(“/x”).then().body(“href”, response -> equalTo(“http://localhost:8080/“ + response.path(“userId”)); |
---|
有一些预定义的匹配器,您可以使用在 io.restassured.matcher.RestAssuredMatchers(或 io.restassured.module.mockmvc.matcher.RestAssuredMockMvcMatchers 如果使用 spring-mock-mvc 模块)中定义。 例如:
Java get(“/x”).then().body(“href”, endsWithPath(“userId”)); |
---|
ResponseAwareMatchers 也可以与另一个 ResponseAwareMatcher 或与 Hamcrest Matcher 组成。 例如:
Java get(“/x”).then().body(“href”, and(startsWith(“http:/localhost:8080/“), endsWithPath(“userId”))); |
---|
and 方法是由io.restassured.matcher.ResponseAwareMatcherComposer静态导入的。
计算响应时间
从 REST Assured 2.8.0 开始支持测量响应时间,例如:
Java long timeInMs = get(“/lotto”).time() |
---|
或使用特定时间单位:
Java long timeInSeconds = get(“/lotto”).timeIn(SECONDS); |
---|
其中 SECONDS 只是一个标准的 TimeUnit。 您还可以使用 DSL 验证:
Java when(). get(“/lotto”). then(). time(lessThan(2000L)); // Milliseconds |
---|
或
Java when(). get(“/lotto”). then(). time(lessThan(2L), SECONDS); |
---|
需要注意的是,您只能参考性地将这些测量数据与服务器请求处理时间相关联(因为响应时间将包括 HTTP 往返和 REST Assured 处理时间等,不能做到十分准确)。
认证
REST assured 还支持多种认证方案,例如 OAuth,摘要,证书,表单和抢占式基本认证。 您可以为每个请求设置身份验证:
Java given().auth().basic(“username”, “password”). .. |
---|
也可以为所有请求定义身份验证:
Java RestAssured.authentication = basic(“username”, “password”); |
---|
或者您也可以使用 specification.
基本认证
有两种类型的基本认证,抢占和 “受质询的基本认证”。
抢占式
服务器在某些情况下给出未授权响应之前发送基本认证凭证,从而减少进行附加连接的开销。 大多数情况下可以这么使用:
Java given().auth().preemptive().basic(“username”, “password”).when().get(“/secured/hello”).then().statusCode(200); |
---|
受质询的基本认证
使用 “受质询的基本认证” 时,REST Assured 将不提供凭据,除非服务器已明确要求。 这意味着 REST Assured 将向服务器发出一个附加请求,以便进行质询,然后再次处理相同的请求,但此时会在 header 中设置基本凭据。
Java given().auth().basic(“username”, “password”).when().get(“/secured/hello”).then().statusCode(200); |
---|
摘要认证
目前只支持受质询的摘要认证:
Java given().auth().digest(“username”, “password”).when().get(“/secured”). .. |
---|
表单认证
表单认证在互联网上非常流行。 它通常与用户在网页上填写其凭据(用户名和密码),然后在按某种类型的登录按钮时发起请求。 提供表单身份验证基础的一个非常简单的 HTML 页面可能如下所示
| HTML