【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

    io.rest-assured
    json-schema-validator
    3.0.1

    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 {

    1. @Test <br /> public void validates_schema_in_classpath() {<br /> _// 定义json_<br /> String json = ... _// Greeting response_
    2. _// 验证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

    {params(“firstName”)}
    {params(“lastName”)}

    在请求中返回了一个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

    sudo
    make me a sandwich!

    可以声明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


    Chocolate
    Coffee


    Paper
    Pens


    Kathryn’s Birthday

    写一个测试用例来检验类型为 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 = from(response).getList(“shopping.category.find { it.@type == ‘groceries’ }.item”);

    如果 groceries 是您对这个响应里唯一的关注点,也可以使用一个捷径:

    Java
    // Get the response body as a String
    List groceries = get(“/shopping”).path(“shopping.category.find { it.@type == ‘groceries’ }.item”);

    深度优先搜索
    实际上之前的例子还可以继续简化:

    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 bookTitles = from(response).getList(“store.book.findAll { it.price < 10 }.title”);

    例 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 winnerIds = from(json).get(“lotto.winners.winnerId”)

    或者更高效一些:

    Java
    JsonPath jsonPath = new JsonPath(json).setRoot(“lotto”);
    int lottoId = jsonPath.getInt(“lottoId”);
    List winnerIds = jsonPath.get(“winners.winnderId”);

    注意这里我们独立地使用了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 allCookies = response.getCookies();
    // 获取单个 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 = new ArrayList();
    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,内容类型和正文。
    响应体
    请参阅使用示例,例如JSONXML.
    您还可以将响应正文映射到 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





    1. <tr><td colspan='2'><input name="submit" type="submit"/></td></tr><br /> </table><br /> </form><br /> </body><br /> </html> |

    | —- |

    也就是说,服务器期望用户填写 “j_username” 和 “j_password” 输入字段,然后按 “提交” 登录。 使用 REST Assured,您可以测试受表单身份验证保护的服务,如下所示:

    Java
    given().
    auth().form(“John”, “Doe”).
    when().
    get(“/formAuth”);
    then().
    statusCode(200);

    在 REST 中使用此类表单身份验证时,会导致为检索包含登录详细信息的网页而向服务器发出附加请求。 REST Assured 将尝试解析此页面并查找两个输入字段(用户名和密码)以及表单操作的 URI。 这可能失败,取决于网页的复杂性。 更好的选择是在设置表单身份验证时提供这些详细信息。 在这种情况下,可以:

    Java
    given().
    auth().form(“John”, “Doe”, new FormAuthConfig(“/j_spring_security_check”, “j_username”, “j_password”)).
    when().
    get(“/formAuth”);
    then().
    statusCode(200);

    这样 REST Assured 不需要提出额外的请求并解析网页。 还有一个预定义的 FormAuthConfig 称为springSecurity,如果你使用默认的 Spring Security 属性,可以使用它:

    Java
    given().
    auth().form(“John”, “Doe”, FormAuthConfig.springSecurity()).
    when().
    get(“/formAuth”);
    then().
    statusCode(200);

    CSRF
    如今,服务器要求请求中提供一个CSRF token 是常有的事了,这可以抵御多种类型的攻击。rest-assured 支持解析并自动给服务器供应一个 CSRF token。为此,rest-assured 必须先发起一个追加请求来解析该网站(的部分内容)。
    你可以通过下面的代码启用对 CSRF 的支持:

    Java
    given().
    auth().form(“John”, “Doe”, formAuthConfig().withAutoDetectionOfCsrf()).
    when().
    get(“/formAuth”);
    then().
    statusCode(200);

    现在 rest-assured 将会自动尝试侦测这个网站是否包含 CSRF token 机制。为了使 rest-assured 的暴力破解更加顺利,可能会提供一个 CSRF 域的名称(这里我们假设我们正在使用 Spring 的安全默认值,因此我们可以使用预定义的springSecurity表单认证配置):

    Java
    given().
    auth().form(“John”, “Doe”, springSecurity().withCsrfFieldName(“_csrf”)).
    when().
    get(“/formAuth”);
    then().
    statusCode(200);

    我们至此已经告诉 rest-assured 去查找名为”_csrf”的 CSRF 域了(然而这虽然会比自动侦测更快,也更容易出错)。
    默认情况下 CSRF 值将会作为一个请求参数,但是如果必要你也可以配置其放在请求的 header 中:

    Java
    given().
    auth().form(“John”, “Doe”, springSecurity().withCsrfFieldName(“_csrf”).sendCsrfTokenAsHeader()).
    when().
    get(“/formAuth”);
    then().
    statusCode(200);

    OAuth
    为了使用 OAuth1 和 OAuth2(关于查询/请求参数签名方面的机制),您需要添加Scribe到 classpath 中(如果你正在使用 2.1.0 或者更早之前版本的 rest-assured,请参考旧版指南)。如果是 maven 请添加以下的依赖:

    XML

    org.scribe
    scribe
    1.3.7
    test

    OAuth 1
    OAuth1 要求Scribe在 classpath 中。为使用 auth1 的认证您可以:

    Java
    given().auth().oauth(..). ..

    OAuth 2
    自从 2.5.0 版本您可以依赖于Scribe使用 OAuth2 的认证:

    Java
    given().auth().oauth2(accessToken). ..

    这将会把 OAuth2 的accessToken放入 header 中。想要更加显式的操作可以:

    Java
    given().auth().preemptive().oauth2(accessToken). ..

    这里之所以存在given().auth().oauth2(..)这种语法是为了向后兼容 (做的是相同的事情)。如果你需要在请求参数中提供一个 OAuth2 token,您需要把Scribe放在 classpath 下,接下来:

    Java
    given().auth().oauth2(accessToken, OAuthSignature.QUERY_STRING). ..

    自定义身份验证
    rest-assured 允许您创建一个自定义的身份验证。你可以通过实现io.restassured.spi.AuthFilter接口,并作为一个过滤器。假设您的安全机制,是由两个 header 值相加然后组成一个新的叫做”AUTH”的 header(当然这并不安全)。然后您可以这样做(Java 8 的语法):

    Java
    given().
    filter((requestSpec, responseSpec, ctx) -> {
    String header1 = requestSpec.getHeaders().getValue(“header1”);
    String header2 = requestSpec.getHeaders().getValue(“header2”);
    requestSpec.header(“AUTH”, header1 + header2);
    return ctx.next(requestSpec, responseSpec);
    }).
    when().
    get(“/customAuth”).
    then().
    statusCode(200);

    使用AuthFilter而不是Filter的原因是,当我们执行given().auth().none(). ..类似这样的操作时AuthFilters会被自动移除。
    Multi-part 表单数据
    通常我们在向服务器传输大容量的数据时(译者注:比如文件)会使用 multipart 表单数据技术。rest-assured 提供了一种multiPart方法来辨别这究竟是文件、二进制序列、输入流还是上传的文本。表单中上传一个文件可以这样:

    Java
    given().
    multiPart(new File(“/path/to/file”)).
    when().
    post(“/upload”);

    它将会假设有一个 control 叫做”file”。在 HTML 中这意味着 input 标签的属性值为 file。为了解释得更清楚请看下面的 HTML 表单:

    HTML



    在这个例子中 control 的名字就是一个属性名为 file 的 input 标签。如果您使用的 control 名不是这个,需要指定:

    Java
    given().
    multiPart(“controlName”, new File(“/path/to/file”)).
    when().
    post(“/upload”);

    在同一个请求中提供多个”multi-parts”事务也是可能的:

    Java
    byte[] someData = ..
    given().
    multiPart(“controlName1”, new File(“/path/to/file”)).
    multiPart(“controlName2”, “my_file_name.txt”, someData).
    multiPart(“controlName3”, someJavaObject, “application/json”).
    when().
    post(“/upload”);

    更多高级使用方法可以使用MultiPartSpecBuilder。举个例子:

    Java
    Greeting greeting = new Greeting();
    greeting.setFirstName(“John”);
    greeting.setLastName(“Doe”);
    given().
    multiPart(new MultiPartSpecBuilder(greeting, ObjectMapperType.JACKSON_2)
    .fileName(“greeting.json”)
    .controlName(“text”)
    .mimeType(“application/vnd.custom+json”).build()).
    when().
    post(“/multipart/json”).
    then().
    statusCode(200);

    你可以通过使用MultiPartConfig指定默认的 control 名和文件名。举个例子:

    Java
    given().config(config().multiPartConfig(multiPartConfig().defaultControlName(“something-else”))). ..

    这就会默认把 control 名配置为”something-else”而不是”file”。
    其它用法请查阅 这篇博客
    对象映射
    rest-assured 支持从 JSON 和 XML 中映射 Java 对象。映射 JSON 需要 classpath 中有 Jackson 或者 Gson 才能使用,XML 则需要 JAXB。
    序列化
    假设我们有下面的 Java 对象:

    | Java
    public class Message {
    private String message;

    1. public String getMessage() {<br /> return message;<br /> }
    2. public void setMessage(String message) {<br /> this.message = message;<br /> }<br />} |

    | —- |

    您需要将这个对象序列化为 JSON 并发送到请求中。可以有多种方式:
    基于 Content-Type 的序列化

    Java
    Message message = new Message();
    message.setMessage(“My messagee”);
    given().
    contentType(“application/json”).
    body(message).
    when().
    post(“/message”);

    在这个例子里,由于请求中的 content-type 被设置为”application/json”,rest-assured 也就会把对象序列化为 JSON。rest-assured 首先会在您的 classpath 中寻找 Jackson,如果没有则使用 Gson。如果您把请求中的 content-type 修改为”application/xml”,rest-assured 将会使用 JAXB 把对象序列化为 XML。如果没有指定 content-type,rest-assured 会按照以下的优先级进行序列化:
    使用 Jackson 2 将对象序列化为 JSON(Faster Jackson (databind))
    使用 Jackson 将对象序列化为 JSON(databind)
    使用 Gson 将对象序列化为 JSON
    使用 JAXB 将对象序列化为 XML
    rest-assured 也关心 content-type 的字符集(charset)等等。

    Java
    Message message = new Message();
    message.setMessage(“My messagee”);
    given().
    contentType(“application/json; charset=UTF-16”).
    body(message).
    when().
    post(“/message”);

    您也可以把Message这个实例序列化为一个表单参数:

    Java
    Message message = new Message();
    message.setMessage(“My messagee”);
    given().
    contentType(“application/json; charset=UTF-16”).
    formParam(“param1”, message).
    when().
    post(“/message”);

    这个 message 对象将会被实例化为 utf-16 编码的 JSON(如果有 Jackson 或者 Gson)。
    由 HashMap 创建 JSON
    您也可以提供一个 Map,由此 rest-assured 可以创建一个 JSON。

    Java
    Map jsonAsMap = new HashMap<>();
    jsonAsMap.put(“firstName”, “John”);
    jsonAsMap.put(“lastName”, “Doe”);
    given().
    contentType(JSON).
    body(jsonAsMap).
    when().
    post(“/somewhere”).
    then().
    statusCode(200);

    这将会产生一个 JSON 数据(JSON payload):

    JSON
    { “firstName” : “John”, “lastName” : “Doe” }

    使用显式序列化器
    如果您的 classpath 中同时有多个对象、或者不考虑 content-type 的设置,可以显示地指定一个序列化器。

    Java
    Message message = new Message();
    message.setMessage(“My messagee”);
    given().
    body(message, ObjectMapperType.JAXB).
    when().
    post(“/message”);

    在这个例子中 message 对象将会被 JAXB 序列化为一个 XML。
    反序列化
    让我们再次假设我们有以下的 Java 对象:

    | Java
    public class Message {
    private String message;

    1. public String getMessage() {<br /> return message;<br /> }
    2. public void setMessage(String message) {<br /> this.message = message;<br /> }<br />} |

    | —- |

    我们需要把响应体反序列化为一个 Message 对象。
    基于 Content-Type 的反序列化
    假设服务端返回一个这样的 JSON:

    JSON
    {“message”:”My message”}

    将它反序列化为一个 Message 对象:

    Java
    Message message = get(“/message”).as(Message.class);

    为此响应体的 content-type 必须是”application/json”(或者其它包含 “json” 的类型)。如果服务端返回:

    XML
    <?xml version=”1.0” encoding=”UTF-8” standalone=”yes”?>

    My message

    且 content-type 是”application/xml”,代码可以完全不用修改:

    Java
    Message message = get(“/message”).as(Message.class);

    自定义类型 content-type 反序列化
    如果服务端返回一个自定义的 content-type,假设是”application/something”,你仍然想使用 rest-assured 的对象映射的话,这有两种方法。你可以使用显式指定的方法或者为自定义的 content-type 注册一个解析器:

    Java
    Message message = expect().parser(“application/something”, Parser.XML).when().get(“/message”).as(Message.class);


    Java
    Message message = expect().defaultParser(Parser.XML).when().get(“/message”).as(Message.class);

    你也可以注册一个默认解析器,或者静态式注册一个自定义的解析器,也可以使用模式(specifications)
    使用显式反序列化器
    如果您的 classpath 下同时有多个对象或者不在意响应体的 content-type,你可以使用显示的反序列化器。

    Java
    Message message = get(“/message”).as(Message.class, ObjectMapperType.GSON);

    配置
    您可以使用ObjectMapperConfig配置预定义的对象映射,并传递给细节配置。举个例子,你可以将 GSON 的命名策略改为 LowerCaseWithUnderscores(译者注:一种策略,将大写字母改为小写字母并添加下划线):

    Java
    RestAssured.config = RestAssuredConfig.config().objectMapperConfig(objectMapperConfig().gsonObjectMapperFactory(
    new GsonObjectMapperFactory() {
    public Gson create(Class cls, String charset) {
    return new GsonBuilder().setFieldNamingPolicy(LOWER_CASE_WITH_UNDERSCORES).create();
    }
    }
    ));

    这里为 GSON、JAXB、Jackson 和 Faster Jackson 都预定义了用来映射实例的工厂。
    自定义
    默认情况下 rest-assured 将会扫描 classpath 中各种各样的对象映射。如果您想要集成一种对象映射,默认是不支持的,如果您已经做好了封装,可以实现io.restassured.mapper.ObjectMapper 接口。告诉 rest-assured 使用您的对象映射或者将其作为 body 方法里的第二个参数:

    Java
    given().body(myJavaObject, myObjectMapper).when().post(“..”)

    或者您可以静态式定义:

    Java
    RestAssured.config = RestAssuredConfig.config().objectMapperConfig(new ObjectMapperConfig(myObjectMapper));

    更多例子参阅这里
    自定义解析器
    rest-assured 提供了预定义的解析器,例如 HTML、XML 和 JSON 的。但是您可以通过注册预置的解析器来解析现在不支持的内容类型:

    Java
    RestAssured.registerParser(, );

    例如注册一个可以解析’application/vnd.uoml+xml’类型的 XML 解析器:

    Java
    RestAssured.registerParser(“application/vnd.uoml+xml”, Parser.XML);

    您也可以注销一个解析器:

    Java
    RestAssured.unregisterParser(“application/vnd.uoml+xml”);

    解析器可以指定于每个请求中:

    Java
    get(..).then().using().parser(“application/vnd.uoml+xml”, Parser.XML). ..;

    然后使用模式
    默认解析器
    有时如果响应中不包含任何 content-type,指定一个默认的解析器会很有用。

    Java
    RestAssured.defaultParser = Parser.JSON;

    你也可以为一次请求指定默认的解析器:

    Java
    get(“/x”).then().using().defaultParser(Parser.JSON). ..

    或者使用响应体模式
    默认值
    rest-assured 发起请求时默认使用 localhost 的 8080 端口.如果你需要换个端口:

    Java
    given().port(80). ..

    或者简单些:

    Java
    ..when().get(“http://myhost.org:80/doSomething“);

    您也可以改变默认的基本 URI、基本路径、端口和认证 scheme:

    Java
    RestAssured.baseURI = “http://myhost.org“;
    RestAssured.port = 80;
    RestAssured.basePath = “/resource”;
    RestAssured.authentication = basic(“username”, “password”);
    RestAssured.rootPath = “x.y.z”;

    这意味着类似get(“/hello”)这样的请求实际上会被解析为http://myhost.org:80/resource/hello))。其它的默认值也可以被指定:,附带身份认证中的用户名和密码属性。关于设置根路径参考 这里

    Java
    RestAssured.filters(..); // List of default filters
    RestAssured.requestSpecification = .. // Default request specification
    RestAssured.responseSpecification = .. // Default response specification
    RestAssured.urlEncodingEnabled = .. // Specify if Rest Assured should URL encoding the parameters
    RestAssured.defaultParser = .. // Specify a default parser for response bodies if no registered parser can handle data of the response content-type
    RestAssured.registerParser(..) // Specify a parser for the given content-type
    RestAssured.unregisterParser(..) // Unregister a parser for the given content-type

    您可以设置重置为标准的 baseURI (localhost),basePath(空),标准端口(8080),标准根路径(“”),默认身份认证 scheme(none)和 URL 编码启用(true):

    Java
    RestAssured.reset();

    模式复用
    与其复制一份响应的断言或者请求参数(的代码)到另一个测试用例中,我们可以使用 RequestSpecBuilder或者ResponseSpecBuilder定义一个规范提案。
    举个例子,在多个测试用例中,我们都涉及到这样的内容:判断响应码是否为 200,JSON 数组 x.y 的长度是否是 2,您可以定义一个 ResponseSpecBuilder:

    Java
    ResponseSpecBuilder builder = new ResponseSpecBuilder();
    builder.expectStatusCode(200);
    builder.expectBody(“x.y.size()”, is(2));
    ResponseSpecification responseSpec = builder.build();
    // Now you can re-use the “responseSpec” in many different tests:
    when().
    get(“/something”).
    then().
    spec(responseSpec).
    body(“x.y.z”, equalTo(“something”));

    在这个例子中需要重用的数据定义并合并在”responseSpec”,并且仅当所有预期都通过时用例才能通过。
    您也可以将相同的请求参数重用:

    Java
    RequestSpecBuilder builder = new RequestSpecBuilder();
    builder.addParam(“parameter1”, “parameterValue”);
    builder.addHeader(“header1”, “headerValue”);
    RequestSpecification requestSpec = builder.build();
    given().
    spec(requestSpec).
    param(“parameter2”, “paramValue”).
    when().
    get(“/something”).
    then().
    body(“x.y.z”, equalTo(“something”));

    这里请求数据合并在”requestSpec”中,由此上面例子中实际请求参数包括两个 (“parameter1” 和 “parameter2”) 和一个 header(“header1”)。
    过滤器
    过滤器会在请求实际发起之前侦测和改变该请求的内容,也可以在响应体实际返回之前拦截并改变。您可以将其理解为 AOP 中的 around advice(译者注:可以自行搜索切片编程)。过滤器也可以用在认证 scheme、session 管理、日志中。创建一个过滤器需要实现io.restassured.filter.Filter接口。使用过滤器:

    Java
    given().filter(new MyFilter()). ..

    rest-assured 提供了几个过滤器:
    io.restassured.filter.log.RequestLoggingFilter: 可以打印出请求模式的细节。
    io.restassured.filter.log.ResponseLoggingFilter: 可以打印响应信息的细节如果响应体的状态码匹配 given 方法的参数。
    io.restassured.filter.log.ErrorLoggingFilter: 如果发生了异常(状态码在 400 和 500 之间),过滤器将会打印响应的内容。
    Response Builder
    如果您想要通过一个过滤器改变Response ,可以使用ResponseBuilder创建一个基于原始 response 的新实例。比如把原始响应体改为 something:

    Java
    Response newResponse = new ResponseBuilder().clone(originalResponse).setBody(“Something”).build();

    日志
    在大量的用例中,打印出响应或者请求的细节将有助于创建正确的预期、发送准确的请求。为此您可以使用 rest-assured 预定义的过滤器,或者使用其中的快捷方法。
    请求日志
    自 1.5 版本起 rest-assured 支持对特定的请求打日志,之前的做法是使用RequestLoggingFilter。注意打印日志后 HTTP Builder 和 HTTP Client 会添加额外的 header 内容。这个过滤器可以只记录特定请求的特定细节。换句话说,你可以不关注RequestLoggingFilter记录的有关实际往服务端发送的内容。因为随后的其它过滤器会在日志记录后改变这个请求。如果你想要记录实际发送的内容,参阅HTTP Client logging docs ,或者使用第三方工具例如Wireshark。示例如下:

    Java
    given().log().all(). .. // Log all request specification details including parameters, headers and body
    given().log().params(). .. // Log only the parameters of the request
    given().log().body(). .. // Log only the request body
    given().log().headers(). .. // Log only the request headers
    given().log().cookies(). .. // Log only the request cookies
    given().log().method(). .. // Log only the request method
    given().log().path(). .. // Log only the request path

    响应日志
    如果您想打印除了状态码以外的响应信息,可以:

    Java
    get(“/x”).then().log().body() ..

    这样做,无论是否有异常错误发生,都会打印出响应信息。如果您希望只有当错误发生时才打印响应信息,可以:

    Java
    get(“/x”).then().log().ifError(). ..

    您也可以记录响应里包括状态码、header、cookie 的所有细节:

    Java
    get(“/x”).then().log().all(). ..

    也可以只记录状态码、header 或者 cookie:

    Java
    get(“/x”).then().log().statusLine(). .. // Only log the status line
    get(“/x”).then().log().headers(). .. // Only log the response headers
    get(“/x”).then().log().cookies(). .. // Only log the response cookies

    您也可以配置为仅当状态码匹配某个值时才打印响应体:

    Java
    get(“/x”).then().log().ifStatusCodeIsEqualTo(302). .. // Only log if the status code is equal to 302
    get(“/x”).then().log().ifStatusCodeMatches(matcher). .. // Only log if the status code matches the supplied Hamcrest matcher

    认证失败日志
    自 rest-assured2.3.1 版本起,您可以仅当认证失败时记录请求或者响应的日志。为请求打日志:

    Java
    given().log().ifValidationFails(). ..

    为响应打日志:

    Java
    .. .then().log().ifValidationFails(). ..

    同时启用对请求和响应的认证失败记录,可以使用LogConfig:

    Java
    given().config(RestAssured.config().logConfig(logConfig().enableLoggingOfRequestAndResponseIfValidationFails(HEADERS))). ..

    认证失败,仅记录 header。
    还有种针对所有请求的简单写法:

    Java
    RestAssured.enableLoggingOfRequestAndResponseIfValidationFails();

    根路径
    为避免在 body 方法里使用重复的路径,您可以指定一个根路径:

    Java
    when().
    get(“/something”).
    then().
    body(“x.y.firstName”, is(..)).
    body(“x.y.lastName”, is(..)).
    body(“x.y.age”, is(..)).
    body(“x.y.gender”, is(..));

    使用根路径:

    Java
    when().
    get(“/something”).
    then().
    root(“x.y”). // You can also use the “root” method
    body(“firstName”, is(..)).
    body(“lastName”, is(..)).
    body(“age”, is(..)).
    body(“gender”, is(..));

    也可以设置一个默认的根路径:

    Java
    RestAssured.rootPath = “x.y”;

    在许多高级用例中,在根路径上附加一些参数也很有用。您可以使用appendRoot方法:

    Java
    when().
    get(“/jsonStore”).
    then().
    root(“store.%s”, withArgs(“book”)).
    body(“category.size()”, equalTo(4)).
    appendRoot(“%s.%s”, withArgs(“author”, “size()”)).
    body(withNoArgs(), equalTo(4));

    也可以对根路径进行拆分:

    Java
    when().
    get(“/jsonStore”).
    then().
    root(“store.category”).
    body(“size()”, equalTo(4)).
    detachRoot(“category”).
    body(“size()”, equalTo(1));

    路径参数
    在预定义的路径包含变量时,路径参数会很有用。举个例子:

    Java
    String someSubPath = “else”;
    int index = 1;
    get(“/x”).then().body(“something.%s[%d]”, withArgs(someSubPath, index), equalTo(“some value”)). ..

    将会对”something.else[0](译者注:这里只是举个例子)”是否等于”some value”进行判断。
    另一种用法是,如果您有复杂的根路径

    Java
    when().
    get(“/x”).
    then().
    root(“filters.filterConfig[%d].filterConfigGroups.find { it.name == ‘GroupName’ }.includes”).
    body(withArgs(0), hasItem(“first”)).
    body(withArgs(1), hasItem(“second”)).
    ..

    路径参数遵循 Java 的标准格式语法
    注意withArgs方法可以从io.restassured.RestAssured类中静态导入。
    有时当所有在根路径中指定的参数都已经验证过了,只想要验证一个不含多余参数的 body 时,可以使用withNoArgs:

    Java
    when().
    get(“/jsonStore”).
    then().
    root(“store.%s”, withArgs(“book”)).
    body(“category.size()”, equalTo(4)).
    appendRoot(“%s.%s”, withArgs(“author”, “size()”)).
    body(withNoArgs(), equalTo(4));

    Session 支持
    rest-assured 提供了一套简单的管理 session 的方式。您可以在 DSL中预定义一个 session 的 id 值:

    Java
    given().sessionId(“1234”). ..

    上面的代码实际上是这个的简写:

    Java
    given().cookie(“JSESSIONID”, “1234”). ..

    您也可以为所有的请求指定一个默认的sessionId:

    Java
    RestAssured.sessionId = “1234”;

    默认情况下 session id 的名字是JSESSIONID,但是您可以通过使用SessionConfig来修改:

    Java
    RestAssured.config = RestAssured.config().sessionConfig(new SessionConfig().sessionIdName(“phpsessionid”));

    您也可以指定一个 sessionid 并在其它用例中复用,使用RequestSpecBuilder:

    Java
    RequestSpecBuilder spec = new RequestSpecBuilder().setSessionId(“value1”).build();
    // Make the first request with session id equal to value1
    given().spec(spec). .. // Make the second request with session id equal to value1
    given().spec(spec). .

    从响应对象中获取一个 session id:

    Java
    String sessionId = get(“/something”).sessionId();

    Session 过滤器
    2.0.0 版本起您可以使用session filter截获并提供一个 session,举个例子:

    | Java
    SessionFilter sessionFilter = new SessionFilter();
    given().
    auth().form(“John”, “Doe”).
    filter(sessionFilter).
    when().
    get(“/formAuth”).
    then().
    statusCode(200);

    given().
    filter(sessionFilter). // Reuse the same session filter instance to automatically apply the session id from the previous response
    when().
    get(“/x”).
    then().
    statusCode(200); | | —- |

    要想获取由SessionFilter截获的 session id:

    Java
    String sessionId = sessionFilter.getSessionId();

    SSL
    在多数场景下,SSL 能顺利运转,这多亏于 HTTP Builder 和 HTTP Client。如果服务端使用了无效的证书,然而有些例子下还是会出错。最简单的方法您可以使用”relaxed HTTPs validation”:

    Java
    given().relaxedHTTPSValidation().when().get(“https://some_server.com“). ..

    也可以为所有的请求静态定义这个配置:

    Java
    RestAssured.useRelaxedHTTPSValidation();

    或者放在请求指定中进行复用。
    这将会假定我们使用 SSL 协议。想要改变需要覆盖relaxedHTTPSValidation方法:

    Java
    given().relaxedHTTPSValidation(“TLS”).when().get(“https://some_server.com“). ..

    您也可以创建一个 Java keystore 文件并执行一些细粒度的操作。这并不难,首先阅读指南,然后在 rest-assured 中使用 keystore:

    Java
    given().keystore(“/pathToJksInClassPath”, ). ..

    或者为每一个请求指定:

    Java
    RestAssured.keystore(“/pathToJksInClassPath”, );

    您也可以定义一个可复用的keystore。
    如果您已经使用密码载入了一个 keystore,可以将其作为可信的 keystore:

    Java
    RestAssured.trustStore(keystore);

    也可以找到一些相关的示例。
    有关更多 SSL 的高级配置参阅SSL Configuration
    SSL 无效主机名
    如果证书指定了一个无效的主机名,并且您无需创建和导入一个 keystore。自 2.2.0 起您可以:

    Java
    RestAssured.config = RestAssured.config().sslConfig(sslConfig().allowAllHostnames());

    让所有请求支持所有的主机名。

    Java
    given().config(RestAssured.config().sslConfig(sslConfig().allowAllHostnames()). .. ;

    对于单个请求。
    注意如果您使用了”relaxed HTTPs validation”,那么allowAllHostnames将会默认启用。
    URL 编码
    由于 rest-assured 提供了优秀的自动编码,通常您无需考虑 URL 编码的事情。在有些用例中仍然需要关闭 URL 编码的功能。其中一个原因是在使用 rest-assured 之前可能你已经做过一次编码。为防止两次 URL 编码您需要告诉 rest-assured 禁用这个功能。

    Java
    String response = given().urlEncodingEnabled(false).get(“https://jira.atlassian.com:443/rest/api/2.0.alpha1/search?jql=project%20=%20BAM%20AND%20issuetype%20=%20Bug").asString();
    ..

    或者

    Java
    RestAssured.baseURI = “https://jira.atlassian.com“;
    RestAssured.port = 443;
    RestAssured.urlEncodingEnabled = false;
    final String query = “project%20=%20BAM%20AND%20issuetype%20=%20Bug”;
    String response = get(“/rest/api/2.0.alpha1/search?jql={q}”, query);

    代理(proxy)配置
    从版本 2.3.2 开始 REST Assured 可以更好地支持代理。 例如,如果你有一个代理在 localhost 端口 8888 你可以做:

    Java
    given().proxy(“localhost”, 8888). ..

    如果服务器在本地环境中运行,可以不指定主机名:

    Java
    given().proxy(8888). .. // Will assume localhost

    要使用 HTTPS,需要提供第三个参数(scheme)或使用io.restassured.specification.ProxySpecification。 例如:

    Java
    given().proxy(host(“localhost”).withScheme(“https”)). ..

    其中 host 从 io.restassured.specification.ProxySpecification 静态导入。
    从版本 2.7.0 开始,您还可以为代理指定抢占式基本身份验证。 例如:

    Java
    given().proxy(auth(“username”, “password”)).when() ..

    其中auth是从io.restassured.specification.ProxySpecification静态导入的,也可以将身份验证与不同的 host 相结合:

    Java
    given().proxy(host(“http://myhost.org").withAuth("username“, “password”)). ..

    静态代理配置
    可以为所有请求配置静态代理,例如:

    Java
    RestAssured.proxy(“localhost”, 8888);

    或者:

    Java
    RestAssured.proxy = host(“localhost”).withPort(8888);

    请求规范代理配置
    您还可以创建请求规范并在其中指定代理:

    Java
    RequestSpecification specification = new RequestSpecBuilder().setProxy(“localhost”).build();
    given().spec(specification). ..

    详细配置
    详细配置由RestAssuredConfig实例提供,您可以使用它配置HTTP Client的参数以及重定向日志编码器解码器SessionObjectMapperConnectionSSLParamConfig 设置。 例子:
    特定请求:

    Java
    given().config(RestAssured.config().redirect(redirectConfig().followRedirects(false))). ..

    或使用 RequestSpecBuilder:

    Java
    RequestSpecification spec = new RequestSpecBuilder().setConfig(RestAssured.config().redirect(redirectConfig().followRedirects(false))).build();

    或所有请求:

    Java
    RestAssured.config = config().redirect(redirectConfig().followRedirects(true).and().maxRedirects(0));

    config() and newConfig() can be statically imported from io.restassured.config.RestAssuredConfig.
    编码配置
    使用 [EncoderConfig](http://static.javadoc.io/io.rest-assured/rest-assured/3.0.1/io/restassured/config/EncoderConfig.htmlencoding),可以指定默认的内容 charset(如果没有在 content-type 头中指定)和查询参数 charset 为所有请求。 如果未指定内容字符集,则使用 ISO-8859-1,如果未指定查询参数字符集,则使用 UTF-8。 用法示例:

    Java
    RestAssured.config = RestAssured.config().encoderConfig(encoderConfig().defaultContentCharset(“US-ASCII”));

    如果没有通过使用EncoderConfig中的 defaultCharsetForContentType 方法为此内容类型显式定义字符集,那么还可以指定用于特定内容类型的编码器字符集。 例如:

    Java
    RestAssured.config = RestAssured.config(config().encoderConfig(encoderConfig().defaultCharsetForContentType(“UTF-16”, “application/xml”)));

    如果没有通过使用EncoderConfig中的 defaultCharsetForContentType 方法为此内容类型显式定义字符集,那么还可以指定用于特定内容类型的编码器字符集。 例如:

    Java
    RestAssured.config = RestAssured.config(config().encoderConfig(encoderConfig().defaultCharsetForContentType(“UTF-16”, “application/xml”)));

    这将假设明确指定一个字符集的 “application / xml” 内容类型的 UTF-16 编码。 默认情况下,“application / json” 被指定为使用 “UTF-8” 作为默认内容类型,这是由 [RFC4627](https://www.ietf.org/rfc/rfc4627.txt)指定的。
    避免自动将字符集添加到 content-type 标头
    默认情况下,REST Assured 会自动添加字符集标头。 要完全禁用这个,你可以这样配置EncoderConfig:

    Java
    RestAssured.config = RestAssured.config(config().encoderConfig(encoderConfig().appendDefaultContentCharsetToContentTypeIfUndefined(false));

    解码配置
    使用 [DecoderConfig](http://static.javadoc.io/io.rest-assured/rest-assured/3.0.1/io/restassured/config/DecoderConfig.html),您可以将默认响应内容解码字符集设置为 所有响应。 如果您期望使用不同于 ISO-8859-1 的内容字符集(这是默认字符集),并且响应未在内容类型标头中定义字符集,那么这将非常有用。 用法示例:

    Java
    RestAssured.config = RestAssured.config().decoderConfig(decoderConfig().defaultContentCharset(“UTF-8”));

    您还可以使用 “DecoderConfig” 来指定要应用哪些内容解码器。 当你这样做时,“Accept-Encoding” 头部将被自动添加到请求中,并且响应主体将被自动解码。 默认情况下,启用 GZIP 和 DEFLATE 解码器。 例如要删除 GZIP 解码但保留 DEFLATE 解码,您可以执行以下操作:
    您还可以使用 “DecoderConfig” 来指定要应用哪些内容解码器。 当你这样做时,“Accept-Encoding” 头部将被自动添加到请求中,并且响应主体将被自动解码。 默认情况下,启用 GZIP 和 DEFLATE 解码器。 例如要删除 GZIP 解码但保留 DEFLATE 解码,您可以执行以下操作:

    Java
    given().config(RestAssured.config().decoderConfig(decoderConfig().contentDecoders(DEFLATE))). ..

    如果没有通过使用DecoderConfig中的 “defaultCharsetForContentType” 方法为此内容类型明确定义字符集,则还可以指定要用于特定内容类型的解码器字符集。 例如:

    Java
    RestAssured.config = config(config().decoderConfig(decoderConfig().defaultCharsetForContentType(“UTF-16”, “application/xml”)));

    这将假设明确指定一个字符集的 “application / xml” 内容类型的 UTF-16 编码。 默认情况下,“application / json” 使用 “UTF-8” 作为默认字符集,这是由 [RFC4627](https://www.ietf.org/rfc/rfc4627.txt)指定的。
    Session 配置
    使用 Session 配置,您可以配置 REST Assured 使用的默认 session ID 名称。 默认 session id 名称是JSESSIONID,如果应用程序中的名称不同,并且您希望使用 REST Assured 的 [会话支持](#Session_support),您只需更改它。 用法:

    Java
    RestAssured.config = RestAssured.config().sessionConfig(new SessionConfig().sessionIdName(“phpsessionid”));

    重定向 DSL
    重定向配置可以使用 DSL 指定。 例如。

    Java
    given().redirects().max(12).and().redirects().follow(true).when(). ..

    网络连接配置
    让您配置 REST Assured 的连接设置。 例如,如果要在每个响应后强制关闭 Apache HTTP Client 连接。 如果您在响应中使用少量数据进行大量快速连续请求,则可能需要执行此操作。然而,如果你正在下载(尤其是大量的)分块,你绝不能每个响应后关闭连接的数据。 默认情况下,连接在每个响应后不关闭。

    Java
    RestAssured.config = RestAssured.config().connectionConfig(connectionConfig().closeIdleConnectionsAfterEachResponse());

    Json Config
    JsonPathConfig允许您在 REST Assured 或 JsonPath使用时配置 Json 设置。 它让你配置如何处理 JSON 数字。

    Java
    RestAssured.config = RestAssured.config().jsonConfig(jsonConfig().numberReturnType(NumberReturnType.BIG_DECIMAL))

    HTTP Client 配置
    为 REST Assured 将在执行请求时使用的 HTTP Client 实例配置属性。 默认情况下,REST Assured 会为每个 “given” 语句创建一个新的 http Client 实例。 要配置重用,请执行以下操作:

    Java
    RestAssured.config = RestAssured.config().httpClient(httpClientConfig().reuseHttpClientInstance());

    您还可以使用httpClientFactory方法提供自定义 HTTP Client 实例,例如:

    | Java
    RestAssured.config = RestAssured.config().httpClient(httpClientConfig().httpClientFactory(
    new HttpClientConfig.HttpClientFactory() {

    1. @Override<br /> public HttpClient createHttpClient() {<br /> return new SystemDefaultHttpClient();<br /> }<br /> })); |

    | —- |

    注意,目前你需要提供一个AbstractHttpClient的实例.
    也可以配置默认参数等。
    SSL 配置
    SSLConfig 允许您指定更高级的 SSL 配置,如信任库,密钥库类型和主机名验证器。 例如:

    Java
    RestAssured.config = RestAssured.config().sslConfig(sslConfig().with().keystoreType().and().strictHostnames());

    参数配置
    ParamConfig 允许您配置在 “冲突” 时,更新不同的参数。 默认情况下,所有参数都将合并,因此如果您执行以下操作:

    Java
    given().queryParam(“param1”, “value1”).queryParam(“param1”, “value2”).when().get(“/x”). …

    REST Assured 将发送一个查询字符串param1 = value1&param1 = value2。
    如果这不是您想要的,你可以配置 REST Assured 为 replace 值代替:

    Java
    given().
    config(config().paramConfig(paramConfig().queryParamsUpdateStrategy(REPLACE))).
    queryParam(“param1”, “value1”).
    queryParam(“param1”, “value2”).
    when().
    get(“/x”). ..

    REST Assured 现在将替换param1的值为value2(因为它是最后写的),而不是将它们合并在一起。 您也可以为所有参数类型的每种类型配置统一的更新策略

    Java
    given().config(config().paramConfig(paramConfig().replaceAllParameters())). ..

    也支持在 [Spring Mock Mvc 模块](# Spring Mock Mvc 模块)(配置 [MockMvcParamConfig](http://static.javadoc.io/io.restassured/spring-mock -mvc / 3.0.1 / io / restassured / module / mockmvc / config / MockMvcParamConfig.html)。
    Spring Mock Mvc 模块
    REST Assured 2.2.0 引入了对 [Spring Mock Mvc](http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/test/web/servlet/MockMvc.html)的支持,使用 spring-mock-mvc模块。 这意味着您可以单元测试 Spring Mvc Controller。 例如给出以下 Spring Controller:

    | Java
    @Controller
    public class GreetingController {

    1. private static final String template = "Hello, %s!";<br /> private final AtomicLong counter = new AtomicLong();
    2. @RequestMapping(value = "/greeting", method = GET)<br /> public @ResponseBody Greeting greeting(<br /> @RequestParam(value="name", required=false, defaultValue="World") String name) {<br /> return new Greeting(counter.incrementAndGet(), String.format(template, name));<br /> }<br />} |

    | —- |

    你可以使用 [RestAssuredMockMvc](http://static.javadoc.io/io.restassured/spring-mock-mvc/3.0.1/io/restassured/module/mockmvc/RestAssuredMockMvc.html)来测试它,像这样:

    Java
    given().
    standaloneSetup(new GreetingController()).
    param(“name”, “Johan”).
    when().
    get(“/greeting”).
    then().
    statusCode(200).
    body(“id”, equalTo(1)).
    body(“content”, equalTo(“Hello, Johan!”));

    即它与标准的 REST Assured 语法非常相似。 这使得运行测试真的很快,并且比标准的 REST Assured 更容易引导环境和使用 mock。 你常用的标准 REST Assured 中的大多数东西都可以使用 RestAssured Mock Mvc。 例如(某些)配置,静态规范,日志等等。要使用它,你需要依赖于 Spring Mock Mvc 模块:

    XML

    io.rest-assured
    spring-mock-mvc
    3.0.1
    test

    或者 [下载](http://dl.bintray.com/johanhaleby/generic/spring-mock-mvc-3.0.1-dist.zip)。
    Bootstrapping RestAssuredMockMvc
    静态导入方法:

    Java
    io.restassured.module.mockmvc.RestAssuredMockMvc.
    io.restassured.module.mockmvc.matcher.RestAssuredMockMvcMatchers.

    有关其他静态导入,请参阅文档的 [静态导入](#static-imports)部分。
    为了使用 RestAssuredMockMvc 启动测试,您需要使用一组Controller,MockMvc 实例或 Spring 的 WebApplicationContext 来初始化它。您可以对单个请求执行此操作,如上例所示:

    Java
    given().standaloneSetup(new GreetingController()). ..

    也可以使用静态方法:

    Java
    RestAssuredMockMvc.standaloneSetup(new GreetingController());

    如果静态定义,则不必在 DSL 中指定任何Controller(或 MockMvc 或 WebApplicationContext 实例)。这意味着前面的例子可以写成:

    Java
    given().
    param(“name”, “Johan”).
    when().
    get(“/greeting”).
    then().
    statusCode(200).
    body(“id”, equalTo(1)).
    body(“content”, equalTo(“Hello, Johan!”));

    异步请求
    从版本2.5.0开始 RestAssuredMockMvc 支持异步请求。例如,假设有以下Controller

    | Java
    @Controller
    public class PostAsyncController {

    1. @RequestMapping(value = "/stringBody", method = POST)<br /> public @ResponseBody<br /> Callable<String> stringBody(final @RequestBody String body) {<br /> return new Callable<String>() {<br /> public String call() throws Exception {<br /> return body;<br /> }<br /> };<br /> }<br />} |

    | —- |

    你可以这样测试:

    Java
    given().
    body(“a string”).
    when().
    async().post(“/stringBody”).
    then().
    body(equalTo(“a string”));

    默认超时为 1 秒。也可以使用 DSL 更改超时:

    Java
    given().
    body(“a string”).
    when().
    async().with().timeout(20, TimeUnit.SECONDS).post(“/stringBody”).
    then().
    body(equalTo(“a string”));

    还可以使用AsyncConfig,例如:

    Java
    given().
    config(config().asyncConfig(withTimeout(100, TimeUnit.MILLISECONDS))).
    body(“a string”).
    when().
    async().post(“/stringBody”).
    then().
    body(equalTo(“a string”));

    withTimeout 是从 io.restassured.module.mockmvc.config.AsyncConfig 静态导入的,只是创建一个具有给定超时时间的AsyncConfig的快捷方式。
    全局应用配置以应用于所有请求,如下:

    Java
    RestAssuredMockMvc.config = RestAssuredMockMvc.config().asyncConfig(withTimeout(100, TimeUnit.MILLISECONDS));
    // Request 1
    given().
    body(“a string”).
    when().
    async().post(“/stringBody”).
    then().
    body(equalTo(“a string”));
    // Request 2
    given().
    body(“another string”).
    when().
    async().post(“/stringBody”).
    then().
    body(equalTo(“a string”));

    请求 1 和 2 现在将使用默认超时 100 毫秒。
    添加请求处理器
    Spring MockMvc 已经对请求处理器做了支持,并且您也可以在 RestAssuredMockMvc 中使用。举个例子:

    Java
    given().postProcessors(myPostProcessor1, myPostProcessor2). ..

    请注意,推荐从org.springframework.security.test.web.servlet.request.SecurityMockMvcRequest PostProcessors(例如认证相关的 RequestPostProcessors) 加入请求处理器时,直接使用auth方法,这样可读性更强,当然结果是一样的:

    Java
    given().auth().with(httpBasic(“username”, “password”)). ..

    这里的 httpBasic 静态导入自SecurityMockMvcRequestPostProcessor
    添加结果处理器
    Spring MockMvc 对结果处理器 做了支持,您也可以在 RestAssuredMockMvc 中使用。比方说您想要使用原生的 MockMvc 日志功能:

    Java
    .. .then().apply(print()). ..

    这里的print是从org.springframework.test.web.server.result.MockMvcResultHandlers静态导入的。请注意如果您正在使用 2.6.0 或更早版本的 rest-assured,需要这样使用结果处理器:

    Java
    given().resultHandlers(print()). ..

    但是 rest-assured2.8.0 起不推荐使用这种语法。
    使用结果匹配器
    Spring MockMvc 提供了许多结果处理器,您可以从中获益。RestAssuredMockMvc 也对其中必要的功能进行支持。举个例子,基于某种原因您想要使用结果匹配器验证状态码是否等于 200:

    Java
    given().
    param(“name”, “Johan”).
    when().
    get(“/greeting”).
    then().
    assertThat(status().isOk()).
    body(“id”, equalTo(1)).
    body(“content”, equalTo(“Hello, Johan!”));

    这里的status()是从org.springframework.test.web.server.result.MockMvcResultMatchers静态导入的。注意,您可以使用expect方法,功能上和assertThat一样,但是更接近原生的 MockMvc 的语法
    拦截器
    您也可以在mock请求之前截住并改变MockHttpServletRequestBuilder。您需要先定义一个MockHttpServletRequestBuilderInterceptor,并在 RestAssuredMockMvc 中使用:

    Java
    given().interceptor(myInterceptor). ..

    Specifications
    正如标准的 Rest Assured,你可以使用specifications,以便更好地重用。请注意,RestAssuredMockMvc 的请求规范构建器称为MockMvcRequestSpecBuilder。同样的ResponseSpecBuilder 也可以在 RestAssuredMockMvc 中使用。可以静态定义Specifications(规范),就像标准的 Rest Assured 一样。例如:

    | Java
    RestAssuredMockMvc.requestSpecification = new MockMvcRequestSpecBuilder().addQueryParam(“name”, “Johan”).build();

    RestAssuredMockMvc.responseSpecification = new ResponseSpecBuilder().expectStatusCode(200).expectBody(“content”, equalTo(“Hello, Johan!”)).build();

    given().
    standaloneSetup(new GreetingController()).
    when().
    get(“/greeting”).
    then().
    body(“id”, equalTo(1)); | | —- |

    重置 RestAssuredMockMvc
    如果您使用了任何静态配置,您可以通过调用 RestAssuredMockMvc.reset()方法轻松地将 RestAssuredMockMvc 重置为其默认状态。
    Spring MVC 认证
    spring-mock-mvc的版本`2.3.0’支持身份验证。例如:

    Java
    given().auth().principal(..). ..

    一些认证方法需要 Spring 安全在类路径(可选)。也可以静态定义认证:

    Java
    RestAssuredMockMvc.authentication = principal(“username”, “password”);

    其中principal方法是从RestAssuredMockMvc静态导入的。还可以在请求构建器中定义认证方案:

    Java
    MockMvcRequestSpecification spec = new MockMvcRequestSpecBuilder.setAuth(principal(“username”, “password”)).build();

    使用 Spring Security 测试
    从版本2.5.0也有更好的支持 Spring Security。如果你在类路径中有spring-security-test,你可以这样做:

    Java
    given().auth().with(httpBasic(“username”, “password”)). ..

    其中httpBasic是从SecurityMockMvcRequestPostProcessor静态导入的。这将对请求应用基本认证。为了这个工作,你需要应用SecurityMockMvcConfigurer到 MockMvc 实例。您可以手动执行此操作:

    Java
    MockMvc mvc = MockMvcBuilders.webAppContextSetup(context).apply(SecurityMockMvcConfigurers.springSecurity()).build();

    或者 RESTAssuredMockMvc在你初始化一个AbstractMockMvcBuilder实例时,将自动尝试使用springSecurity配置,比如: 当配置一个”web app context”:

    Java
    given().webAppContextSetup(context).auth().with(httpBasic(“username”, “password”)). ..

    这是一个完整的案例:

    | Java
    import io.restassured.module.mockmvc.RestAssuredMockMvc;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;
    import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    import org.springframework.test.context.web.WebAppConfiguration;
    import org.springframework.web.context.WebApplicationContext;
    import static io.restassured.module.mockmvc.RestAssuredMockMvc.given;
    import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;
    import static org.springframework.security.test.web.servlet.response.SecurityMockMvcResultMatchers.authenticated;
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = MyConfiguration.class)
    @WebAppConfiguration
    public class BasicAuthExample {

    1. @Autowired<br /> private WebApplicationContext context;
    2. @Before public void<br /> rest_assured_is_initialized_with_the_web_application_context_before_each_test() {<br /> RestAssuredMockMvc.webAppContextSetup(context);<br /> }
    3. @After public void<br /> rest_assured_is_reset_after_each_test() {<br /> RestAssuredMockMvc.reset();<br /> }
    4. @Test public void<br /> basic_auth_example() {<br /> given().<br /> auth().with(httpBasic("username", "password")).<br /> when().<br /> get("/secured/x").<br /> then().<br /> statusCode(200).<br /> expect(authenticated().withUsername("username"));<br /> }<br />} |

    | —- |

    你也可以定义一个针对于所有请求的身份认证,比如:

    Java
    RestAssuredMockMvc.authentication = with(httpBasic(“username”, “password”));

    此处 with是从io.restassured.module.mockmvc.RestAssuredMockMvc静态导入的。这里也可以使用request specification
    注入一个用户
    也可以使用 Spring Security 测试注释,例如_@_WithMockUser_@_WithUserDetails。例如,假设您想测试此Controller:

    | Java
    @Controller
    public class UserAwareController {

    1. @RequestMapping(value = "/user-aware", method = GET)<br /> public<br /> @ResponseBody<br /> String userAware(@AuthenticationPrincipal User user) {<br /> if (user == null &#124;&#124; !user.getUsername().equals("authorized_user")) {<br /> throw new IllegalArgumentException("Not authorized");<br /> }
    2. return "Success");<br /> }<br />} |

    | —- |

    您可以看到 userAware() 需要一个 User 作为参数,我们让 Spring Security 使用_@_AuthenticationPrincipal 注入它。要生成测试用户,我们可以这样做:

    Java
    @WithMockUser(username = “authorized_user”)
    @Test public void
    spring_security_mock_annotations_example() {
    given().
    webAppContextSetup(context).
    when().
    get(“/user-aware”).
    then().
    statusCode(200).
    body(equalTo(“Success”)).
    expect(authenticated().withUsername(“authorized_user”));
    }

    注意,也可以不使用注释,而是使用RequestPostProcessor ,例如SecurityMockMvcRequestPostProcessors#user(java.lang.String)).
    参数相关
    MockMvc 没有区分不同类型的参数,所以param,formParam和queryParam目前只是委托给 MockMvc 中的 param。 formParam自动添加application / x-www-form-urlencoded内容类型的头部,就像标准的 Rest Assured 一样。
    Scala 支持
    REST Assured 2.6.0 引入了将 “别名” 添加到 “then” 方法的scala-support模块定义在ResponseMockMvcResponse中调用 “Then”。这样做的原因是then在将来可能是 Scala 中的保留关键字,并且当使用具有此名称的方法时,编译器会发出警告。要启用Then,只需从scala-support模块导入io.restassured.module.scala.RestAssuredSupport.AddThenToResponse类。例如:

    Python
    import io.restassured.RestAssured.when
    import io.restassured.module.scala.RestAssuredSupport.AddThenToResponse
    import org.hamcrest.Matchers.equalTo
    import org.junit.Test
    @Test
    def trying out rest assured in scala with implicit conversion() {
    when().
    get(“/greetJSON”).
    Then().
    statusCode(200).
    body(“key”, equalTo(“value”))
    }

    注意:同样支持 Spring Mock Mvc Module.
    可以像这样使用它:
    SBT:

    JavaScript
    libraryDependencies += “io.rest-assured” % “scala-support” % “3.0.1”

    Maven:

    XML

    io.rest-assured
    scala-support
    3.0.1
    test

    Gradle:

    JavaScript
    testCompile ‘io.rest-assured:scala-support:3.0.1’

    No build manager:
    手动下载 distribution file
    Kotlin 支持
    Kotlin 是由JetBrains开发的一种语言,它与 Java 和 REST Assured 非常好地集成。当使用它与 REST Assured 有一件事,必须逃避when,因为它是 Kotlin 中的保留关键字。例如:

    Kotlin
    Test fun kotlin_rest_assured_example() {
    given().
    param(“firstName”, “Johan”).
    param(“lastName”, “Haleby”).
    when().
    get(“/greeting”).
    then().
    statusCode(200).
    body(“greeting.firstName”, equalTo(“Johan”)).
    body(“greeting.lastName”, equalTo(“Haleby”))
    }

    为了解决这个问题,创建一个extension function,创建一个别名为when时叫做When:

    Kotlin
    fun RequestSpecification.When(): RequestSpecification {
    return this.when()
    }

    代码现在可以像这样写:

    Kotlin
    Test fun kotlin_rest_assured_example() {
    given().
    param(“firstName”, “Johan”).
    param(“lastName”, “Haleby”).
    When().
    get(“/greeting”).
    then().
    statusCode(200).
    body(“greeting.firstName”, equalTo(“Johan”)).
    body(“greeting.lastName”, equalTo(“Haleby”))
    }

    注意,我们不需要任何转义。有关更多详细信息,请参阅this博客文章。
    更多信息
    其他相关信息,请参考 javadoc:
    RestAssured
    RestAssuredMockMvc Javadoc
    Specification package
    一些代码示例:
    REST Assured tests
    JsonPathTest
    XmlPathTest