1. 程式人生 > >rest-assured之靜態導入及簡單使用實例

rest-assured之靜態導入及簡單使用實例

ast amp response buffalo ref red valid 數值類型 str

一、靜態導入

  為了有效的使用rest-assured,官網推薦從下列class中靜態導入方法:

1 io.restassured.RestAssured.*
2 io.restassured.matcher.RestAssuredMatchers.*
3 org.hamcrest.Matchers.*

如果想使用 Json Schema validation(驗證),還需要靜態導入下面的方法:

1 io.restassured.module.jsv.JsonSchemaValidator.*

如果我們正在使用的是 Spring MVC ,我們可以使用 spring--mock-mvc模型的rest-assured DSL來對Spring 的controllers層進行單元測試。為此我們需要從 RestAssuredMockMvc 中導入下面的方法,還不是從 io.restassured.RestAssured 導入:

1 io.restassured.module.mockmvc.RestAssuredMockMvc.*

二、使用實例

1.Json實例

假設 GET請求(to http://localhost:8080/lotto)返回下面的Json:

 1 {
 2 "lotto":{
 3  "lottoId":5,
 4  "winning-numbers":[2,45,34,23,7,5,3],
 5  "winners":[{
 6    "winnerId":23,
 7    "numbers":[2,45,34,23,3,5]
 8  },{
 9    "winnerId":54,
10    "numbers":[52,3,12,11,18,22]
11 }] 12 } 13 }

rest-assured可以非常簡單的發起這個GET請求並且驗證響應結果,比如:我們想驗證 lottoId 是否等於 5 ,可以這樣做:

1 get("/lotto").then().body("lotto.lottoId",equalTo(5));

或者我們想驗證 winnerId的值是否是23,54 :

1 get("/lotto").then().body("lotto.winners.winnerId",hasItems(23,54));

值得註意的是:equalTo()方法和 hasItems()方法是屬於 Hamcrest matchers 的方法,所有我們需要靜態導入 org.hamcrest.Matchers 。

註意:"json path" 使用 Groovy‘s GPath 標記法,不要與 Jayway‘s JsonPath 混淆。

2.以BigDecimal形式返回 floats 和 doubles

  我們可以對rest-assured和JsonPath進行配置,使之以BigDecimal形式返回json裏的數值類型數據,而不是返回 floats 和 doubles,參照下面的json:

1 {
2 
3     "price":12.12 
4 
5 }

默認情況下,我們驗證 price的值是否等於12.12時是這樣做的:

1 get("/price").then().body("price", is(12.12f));

但是如果我們喜歡的話,我們可以通過JsonConfig 來配置rest-assured使之以BigDecimal形式返回json裏的數值類型數據:

1 given().
2         config(RestAssured.config().jsonConfig(jsonConfig().numberReturnType(BIG_DECIMAL))).
3 when().
4         get("/price").
5 then().
6         body("price", is(new BigDecimal(12.12));

3.匿名JSON根節點驗證

  一個json文本並不一定有一個命名好的根節點屬性,驗證這種類型的json,這裏有一個例子:

1 [1, 2, 3]

一個匿名的json根路徑要驗證的話,可以使用 $ 或者是 空字符串 來驗證。例如,我們訪問 http://localhost:8080/json ,然後通過rest-assured來驗證:

1 //第一種方式,使用 $ 代替根節點
2 get("/json").then().body("$",hasItems(1,2,3));
3 
4 //第二種方式,使用 空字符串 代替根節點
5 get("/json").then().body("",hasItems(1,2,3));

4.XML實例

  XML可以使用同樣的方式來驗證。假設向 http://localhost:8080/greetXML 發送一個POST請求,並且返回下面的xml:

1 <greeting>
2    <firstName>{params("firstName")}</firstName>
3    <lastName>{params("lastName")}</lastName>
4 </greeting>

上面的例子返回了一個基於 firstName 和 lastName 請求參數的greeting節點,我們可以通過rest-assured非常簡單展示和驗證,比如驗證 firstName :

1 given().
2          parameters("firstName", "John", "lastName", "Doe").
3 when().
4          post("/greetXML").
5 then().
6          body("greeting.firstName", equalTo("John")).

如果我們想同時驗證 firstName 和 lastName ,我們可以這樣寫:

1 given().
2          parameters("firstName", "John", "lastName", "Doe").
3 when().
4          post("/greetXML").
5 then().
6          body("greeting.firstName", equalTo("John")).
7          body("greeting.lastName", equalTo("Doe"));

或者是使用簡單的寫法:

1 with().parameters("firstName", "John", "lastName", "Doe").when().post("/greetXML").then().body("greeting.firstName", equalTo("John"), "greeting.lastName", equalTo("Doe"));

5.XML命名空間

  為了使響應斷言把命名空間考慮在內,我們需要使用 io.restassured.config.XmlConfig 定義一個命名空間。例如,這裏有一個叫做 namespace-example 的資源位於 http://localhost:8080,返回下面的XML:

1 <foo xmlns:ns="http://localhost/">
2   <bar>sudo </bar>
3   <ns:bar>make me a sandwich!</ns:bar>
4 </foo>

我們可以申明 http://localhost:8080 這個uri並且驗證響應結果:

1 given().
2         config(RestAssured.config().xmlConfig(xmlConfig().declareNamespace("test", "http://localhost/"))).
3 when().
4          get("/namespace-example").
5 then().
6          body("foo.bar.text()", equalTo("sudo make me a sandwich!")).
7          body(":foo.:bar.text()", equalTo("sudo ")).
8          body("foo.test:bar.text()", equalTo("make me a sandwich!"));

這個路徑的語法遵循的是 Groovy‘s XmlSlurper 語法,需要註意的是一直到2.6.0版本,路徑語法都不支持 Groovy‘s XmlSlurper 語法。請看 release notes 查看2.6.0之前的語法。

6.XPath

  我們也可以通過使用X-Path 來驗證XML響應結果,比如:

1 given().parameters("firstName", "John", "lastName", "Doe").when().post("/greetXML").then().body(hasXPath("/greeting/firstName", containsString("Jo")));

或者:

1 given().parameters("firstName", "John", "lastName", "Doe").post("/greetXML").then().body(hasXPath("/greeting/firstName[text()=‘John‘]"));

如果需要在XPath表達式裏面使用命名空間的話,需要在配置中啟用這些選項:

1 given().
2         config(RestAssured.config().xmlConfig(xmlConfig().with().namespaceAware(true))).
3 when().
4          get("/package-db-xml").
5 then().
6          body(hasXPath("/db:package-database", namespaceContext));

namespaceContext是一個javax.xml.namespace.NamespaceContext 的實例 。

三、高級使用實例(復雜的解析以及驗證)

  這正是rest-assured的閃光點所在,因為rest-assured實現了Groovy,rest-assured從 Groovy 的API中獲得了很大的好處。讓我們先從 Groovy 的例子來看:

1 def words = [‘ant‘, ‘buffalo‘, ‘cat‘, ‘dinosaur‘]
2 def wordsWithSizeGreaterThanFour = words.findAll { it.length() > 4 }

  第一行代碼我們只是簡單定義了一個包含字符的list集合,第二行代碼非常的有趣。第二行代碼中我們通過Groovy閉包調用 findAll 方法來查詢list集合中所有長度大於4的字符。這個閉包中有一個叫 it 的內部變量,這個 it 就代表了list集合中的當前元素。這段代碼的結果是一個新的list集合:wordsWithSizeGreaterThanFour ,包含 buffalo and dinosaur。

  下面有一些有趣的方法,也可以在 Groovy 集合中使用:

  • find  ------ 查找第一個匹配閉包斷言(closure predicate)的元素
  • collect   ------封裝集合中的每一個元素調用閉包的返回值
  • sum  -------集合中所有元素之和
  • max/min  --------返回集合中的最大值或最小值

那麽我們在驗證XML和Json時,如何應用這些優點呢???

1.XML例子

  例如我們有個資源 http://localhost:8080/shopping 返回下面的XML:

 1 <shopping>
 2       <category type="groceries">
 3         <item>Chocolate</item>
 4         <item>Coffee</item>
 5       </category>
 6       <category type="supplies">
 7         <item>Paper</item>
 8         <item quantity="4">Pens</item>
 9       </category>
10       <category type="present">
11         <item when="Aug 10">Kathryn‘s Birthday</item>
12       </category>
13 </shopping>

接下來我們要寫一個test方法來驗證 類型為 groceries 的category節點是否包含 Chocolate和Coffee兩個元素,在rest-assured中我們可以這麽寫:

1 when().
2        get("/shopping").
3 then().
4        body("shopping.category.find { it.@type == ‘groceries‘ }.item", hasItems("Chocolate", "Coffee"));

那麽上面的例子當中發生了什麽呢?首先使用XPath方法 shopping.category 獲取所有的category的一個list集合,在這個list集合中我們調用 find 方法,返回type屬性值等於"groceries"的單個category節點,在這個category節點中我們繼續獲得了所有item元素。從上面可以看出category節點下不止一個item元素,所以會返回一個list集合,然後我們通過Hamcrest matcher 的 hasitems 方法來驗證這個list。這就是上面這個例子整個執行過程!

  但是如果我們想獲得上面的item,然後又不想使用 Hamcrest matcher 的 hasitems 方法來驗證,那麽我們可以使用XmlPath:

1 // 獲得response,並且以字符串輸出
2 String response = get("/shopping").asString();
3 // 從response中獲得groceries,"from"是從XmlPath類中靜態導入的 
4 List<String> groceries = from(response).getList("shopping.category.find { it.@type == ‘groceries‘ }.item");

如果在response中我們僅僅關心的是 groceries ,我們還可以這樣做:

1 // 獲得response,並以字符串形式輸出
2 List<String> groceries = get("/shopping").path("shopping.category.find { it.@type == ‘groceries‘ }.item");

1.1 深度優先搜索

  事實上,前面的例子我們還可以進一步簡化一下:

1 when().
2        get("/shopping").
3 then().
4        body("**.find { it.@type == ‘groceries‘ }", hasItems("Chocolate", "Coffee"));

  ** 是一種在XML文件中做深度搜索的捷徑。我們搜索第一個具有type屬性值等於"groceries"的節點,註意我們並沒有在"item"這個Xml路徑結束,原因是在category節點返回item值的list集合時toString() 方法被自動調用了。

rest-assured之靜態導入及簡單使用實例