您好,登錄后才能下訂單哦!
本篇內容主要講解“java的rest-assured怎么使用”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“java的rest-assured怎么使用”吧!
關于rest-assured
rest-assured 是一個能夠簡化測試rest服務的Java DSL,像ruby或者python一樣的動態語言去測試和驗證http服務。基于java并且兼容了groovy動態語言的特性,使我們像寫腳本語言一樣去測試http服務。
例如:你的http服務( http://localhost:8080/lotto/{id})返回一個如下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("/lotto").then().body("lotto.lottoId", equalTo(5));
或者你想斷言下 winnerId是不是 23 和 54:
get("/lotto").then().body("lotto.winners.winnerId", hasItems(23, 54));
如果看起來很簡單,have a try?
rest-assured小試牛刀
在我們沒有運行測試用例之前,我們需要把**rest-assured**的maven依賴先引入
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>3.0.0</version>
<scope>test</scope>
</dependency>
RestAssured這個類是整個測試框架的請求入口,類的內部定義了一系列靜態方法,包括我們常用的POST, GET, PUT, DELETE, OPTIONS, PATCH and HEAD等請求類型,請求響應結果
能用于我們常用的驗證和斷言。
RestAssured.get方法請求http服務
Response response = RestAssured.get("http://localhost/greting?id=5");
請求響應結果response中定義了一系列的json轉換方法,你可以很簡單把你的結果轉換成
json等字符串直接輸出
response.asString();
或者對應實體bean轉換為json對象或者xml。
//json
GreetingBean as = response.as(GreetingBean.class);
//xml
XmlPath xmlPath = response.xmlPath();
也可以把返回結果進行驗證是不是你想要的結果
response.then().statusCode(200).body("name",equalTo("test"));
看到這里你可能認為**rest-assured**提供的方法的確很簡單,但是我把httpclient或者
okhttp封裝一下,也可以達到這個效果,我是一個程序員,我就是喜歡重復造輪子,因為這樣才可以提高我自己的編程水平,那么OK,你一定要造一個比它還好用的輪子。
對于上面的http測試請求還是可以在簡化,能用小程序實現的,決不用大程序。
第一步:
import static io.restassured.RestAssured.given;
第二步:
get("http://localhost/greting?id=5")
我們就可以使用簡單的get,post或者delete發送我們的請求,并且可以獲得響應結果進行斷言返回結果是否正確。
雖然我們在使用別人東西,但是我們也要知其然知其所以然,刨根問底。如果你足夠仔細,打開源碼一識真面目,其實你會發現**rest-assured**本身也沒有什么神秘,他就是充分利用了java多態的特性,對接口進行了高度的繼承和封裝。查看get或者post等一系列http請求方法的實現,你會發現所有的請求體Request,rest-assured本身都對他進行了重新定義,即RequestSpecification,這只是一個接口,它的實現類則是TestSpecificationImpl,這里面則是封裝了標準的http請求(如下,截取了其中的一部分,來自于類io.restassured.internal.TestSpecificationImpl),它是使用groovy語言進行實現。
/**
* {@inheritDoc}
*/
Response get(String path, Object... pathParams) {
requestSpecification.get path, pathParams
}
/**
* {@inheritDoc}
*/
Response post(String path, Object... pathParams) {
requestSpecification.post path, pathParams
}
/**
* {@inheritDoc}
*/
Response put(String path, Object... pathParams) {
requestSpecification.put path, pathParams
}
/**
* {@inheritDoc}
*/
Response delete(String path, Object... pathParams) {
requestSpecification.delete path, pathParams
}
groovy是什么?Groovy是一種基于JVM(Java虛擬機)的敏捷開發語言,它結合了Python、Ruby和Smalltalk的許多強大的特性,Groovy 代碼能夠與 Java 代碼很好地結合,也能用于擴展現有代碼。
你可以再反過來看看返回結果response也是按照這種思路,里面也有一個實現類即ResponseSpecificationImpl。這里也就契合了為什么一開始我們為什么說rest-assured是基于java DSL(*DSL是一種為了特定任務而設計的開發語言* )框架。
rest-assured優勢
* 足夠簡單,短,而且編寫測試用例快(*應該是程序員為啥找不到女朋友的原因吧*)。
* 順序控制結構(*最簡單的結構莫過于此,執行這條語句然后執行下一條語句的形式*)
* 符合契約編程思想(*如果前置條件滿足的情況下調用函數,那么函數的執行將確立后置條件*)
rest-assured系統測試
耐心看了上面的內容,相信你對這個測試框架有了個整體的了解,但是在現實場景中根本不可能使用java的main函數直接調用RestAssured里面的靜態函數,因為這樣寫出來的測試用例是不容易維護的,也是不可移植的,因為這些測試用例今天你是簡單在打包前跑了下測試用例,確定沒有錯誤后,打成測試包,但是之后可能也對這個產品進行持續集成(CI server或者jenkins等),又或者這個產品的用戶量比較大我們需要在Jmeter或者loaderunner中,跑下腳本,測試性能。這時我們要把*rest-assured*結合*Junit*(或者一些自己擅長的單元測試框架testNG等)進行使用。
下面簡單介紹下幾種常見的測試用例場景:
第一步,確保你已經引入Junit和rest-assured包。
并且在引入類的同時進行靜態化,如下:
import static io.restassured.RestAssured.get;
import static io.restassured.RestAssured.given;
import static io.restassured.RestAssured.post;
import static org.hamcrest.Matchers.*;
@Before
public void setup() {
RestAssured.baseURI = "http://localhost";
RestAssured.port = 8080;
}
這里是使用Junit的注解,在運行測試用例之前的準備工作。這里我們配置了ip地址和端口。看到這里有的同學可能要問了我的請求是基于https單向請求,那么我們可以在setup函數中添加 :
`RestAssured.config.getSSLConfig().relaxedHTTPSValidation();`
這個設置代表信任所有客戶端,不用攜帶任何可信任證書,直接能夠請求到服務端,如果這時你使用OKHttp或者httpURLConnection,你可能就要花時間自己實現繞過https認證了,可能你現在手頭有一份可信任證書,想要模擬真是的瀏覽器環境,你可以這樣設置:
RestAssured.config.getSSLConfig().trustStore("test.truststore","123456");
我曾經自己原生的java語言以及httpclient實現過基于證書的雙向認證過程[具體請查看源碼](https://github.com/strictnerd/LearningSummary/tree/master/src/main/java/com/clq),已經精簡到不能在精簡,還寫了個大概十行左右的代碼,如果不參考之前寫的,我可能還要翻開API看看到底是怎么調用的。但是rest-assured就跟我們做了很好的封裝如下:
RestAssured.certificate("clq.truststore", "123456","clq.p12", "123456", CertificateAuthSettings.certAuthSettings().keyStoreType("PKCS12").trustStoreType("jks"));
因為代碼的封裝不夠好,降低了我們的工作效率,很明顯rest-assured提高了我們的工作效率,降低了我們在工作中可能出錯的機率。
其實它這里面不僅做了單雙向認證的封裝,我們平時常見的用戶名密碼登錄、oauth認證、代理請求等等。
第二步,開始我們的rest服務測試
get請求測試
@Test
public void greetingTest() {
given().param("name", "clq")
.then().statusCode(200)
.body("id", equalTo(2),"content", containsString("Hello"))
.when().get("/greeting");
}
這一大串的順序控制結構代碼的含義就是,給出參數name,當我發送get請求之后,那么你給我返回響應碼200,并且id=2,content為hello。
如果你的這個rest服務請求測試有一定的特殊性,那么你可以在這個測試用例中進行另外的聲明。如下:
@Test
public void greetingTest() {
try {
RestAssured.requestSpecification = new RequestSpecBuilder().addCookie("cookie","123456").build();
given().param("name", "clq")
.then().statusCode(200)
.body("id", equalTo(2),"content", containsString("Hello"))
.when().get("/greeting");
}finally {
RestAssured.reset();
}
}
使用完之后,記得在finally里面進行reset,因為有可能會影響其它的測試用例。同樣的我們舉一個基于json請求的post實例,(這個框架可不僅支持基于json格式body傳參,也支持我們常用的form表單或者xml傳參。)
@Test
public void postTest() {
Map<String, Object> map = new HashMap<String, Object>();
map.put("id", 123412);
map.put("addr", "zz");
map.put("age", Arrays.asList(12,27,23,41));
given().contentType(ContentType.JSON)
.body(JSON.toJSONString(map)).proxy(ProxySpecification.host("192.168.1.11").withPort(2010))
.then().statusCode(200)
.body("addr", equalTo("zz"), "id", equalTo(123412), "age[1]", is(27))
.time(lessThan(1L),TimeUnit.SECONDS)
.when().post("/welcome");
}
這個post請求,我在這里設置了特別多的場景,首先是requestBody里面的json傳參,并且使用代理192.168.1.11:2010,當我發送post請求后,那么給我返回響應碼200,body里面的結果符合預期(里面內置了hamcrest這個包,它的主要作用是response返回結果進行驗證)。這些場景也是比較常見的,比如說,我的后臺要添加一個這樣的功能,支持微信公眾號服務的調用,但是我的整個后臺服務都是部署在內網,只有微信調用微信公眾號獲取openid的這一部分需要使用外網,于是搭建了一個外網的代理服務器,那么我就可以基于http請求的代理服務,只讓這部分rest服務訪問外網。
我們現實場景中還有一些經常使用的像文件上傳和下載之類的,它也是支持的。
文件上傳,并且在上傳文件的同事支持參數的傳遞。
@Test
public void uploadFile() {
Response post = given().param("id", "123456")
.multiPart("file", new File("D:/zzrd.jpg"))
.post("/file");
Assert.assertEquals("123456", post.asString());
}
文件下載如下:
@Test
public void downloadFile() {
Response response = given().get("/export");
byte[] bytes = response.asByteArray();
BufferedOutputStream bos = null;
try {
bos = new BufferedOutputStream(new FileOutputStream(new File("d:/xxoo.xls")));
bos.write(bytes);
} catch (FileNotFoundException e) {
//TODO
e.printStackTrace();
} catch (IOException e) {
//TODO
e.printStackTrace();
}finally {
try {
if(bos != null) {
bos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
rest-assured使用場景
我的系統測試非常復雜,有基于表單的,基于json數據格式的,還有使用了xml格式,有部分返回的數據結構也很復雜,有的接口請求地址或者端口是不一樣的,或者使用了代理等功能。
你可以直接使用rest-assured來解決你碰到的這些實際問題。
我是不是可以在業務代碼的請求中直接使用rest-assured?
其實這個我是不推薦的,因為我曾經在我機器上,基于我自己的系統對rest-assured和httpclient做了比較,分別單線程測試(*分別請求1000次,rest-assured耗時85s,httpclient耗時79s*)后來我自己也做過多線程測試,無論怎么測試,得出的結論就是httpclient也比rest-assured快。當然這個可能也不一定準確,服務不同環境不同,測試結果也會隨之改變。畢竟rest-assured底層對httpclient又進行了一次封裝,而且使用了groovy,groovy雖然是一門動態語言,但是他還是基于jvm平臺的,最后還是編譯成了class。個人認為,groovy除了在jvm平臺上執行,并且寫的腳本足夠短之外,跟其它的ruby或者python等腳本語言相比,是沒有什么優勢的。但是他作為測試用例來用,優勢還是非常大的,因為測試用例,不是線上環境,對性能沒什么特別要求。
我使用了springmvc Controller可以使用rest-assured做接口測試嗎?
其實對于這個rest-assured也有對應的spring-mock-mvc,但是spring官方也有基于spring-test接口測試,要是還用rest-assured提供的,老感覺有一種拿著錘子找釘的感覺。
測試帶給我們的好處
測試給我們的產品帶來的好處是非常多的,這里我們只是基于rest API進行測試,在單元測試中來說,這是一個粗粒度的測試,如果想更加詳細,像基于h3數據庫的腳本測試,但是現在我們大部分框架都使用了jpa,這個測試能給我們帶來一定好處,但是工作量也是很可觀的,該不該進行一些基于h3內存數據庫的模擬測試,這里我們自己拿捏,不做過多的建議。至于基于mock業務邏輯的隔離測試,當我們碰到復雜業務邏輯,或者在某種環境下,某個場景難于模擬,如果我們使用了mock,這種場景完全可以避免掉。這種測試該做還是要做的,下面我們可以簡單說下單元測試本身給我們帶來哪些明面上的好處。
首先應該就是它是一種驗證行為,而且具有一定的可回歸性。
我們只是在每完成一個功能之后寫了一個測試用例,立刻可以驗證我們的功能是通過的。當我們的一個模塊或者一個大的功能通過之后,我們可以基于maven快速的運行所有的單元測試。來保證我們的功能在本地是通過測試的。其實就是在開發后期,我們看著某一塊功能或者業務邏輯很不爽(這是別人寫的),那么我們就可以直接修改功能或者重構,之后我們就可以利用測試用例來保證沒有破壞其他的設計,說白了單元測試能給我們改善設計帶來信心。
單元測試代碼更具有可維護性,在某種程度上,可以認為是一種文檔的行為,但是帶來效果可能比文檔還要好。
一套系統,我開發出來,可能過幾天交給AA了,2年后交給了CC,CC怎么才知道后臺服務系統是完全沒有問題的,或者說他怎么知道某個rest服務的目的是什么。如果說我們測試用例中寫了完整的輸入和輸出的斷言機制,整體系統的代碼可讀性都會增強。
能夠在某種程度上提升代碼質量。
這一點我也認為是非常重要的,當你編寫完一個簡單的功能時,你運行一下,輸入一些邊界條件,保證程序是可運行的。這一點是必須的,但是當你出現問題,通常我們調試代碼的過程都是打個斷點,進入代碼內部進行詳細分析,這時你對你的剛剛完成的業務邏輯有個整體的認識,這時如果你發現有不合適的地方,或者代碼冗余的地方,你應該開始調整了。特別是當你使用mock進行隔離測試時,有時為了測試某一個場景,你不得不解耦合(因為這樣讓你更容易測試),在不知不覺中提升了自己的代碼質量。
當然上述都是一些單元測試的好處,測試本來都應該是軟件開發的一部分,這些都是不可否認的。甚至有人提出了TDD,先編寫測試用例,測試用例來確定要編寫什么產品代碼,這些都充分說明了單元測試的重要性。
所以我們不僅要寫測試用例,還要寫好測試用例。
系統測試覆蓋率依然少的可憐?
其實究其原因無非就是產品更新迭代快需要快速占領市場,或者項目趕得實在太緊急,根本沒有時間寫測試用例,這里一般都是說沒有時間寫測試用例,但是還是要測試的。我感覺除了一些業界大牛外,在自己的一段業務代碼沒有做測試前,誰敢保證完全沒有任何問題。再說業界大牛估計寫業務代碼的也不多吧。所以我經常就發現一些現象就是,大部分人在這種情況下,對于rest服務接口,直接簡單省事的用一個httpURLconnection輪番測試所有的接口,最后測著測著自己的測試代碼都有問題了,這還如何保證自己服務端代碼的質量呢?有的同學可能比較擅長使用一些工具,像谷歌的postman或restclient等http接口測試工具,直接把請求拷貝過去,參數添加上去,運行下,OK!有些運用熟練地同學發現里面還可以收藏,把你以前添加的接口收藏到一個列表中,以后可以繼續使用。在某種程度上來說,他提高了我們一些效率,但是難道我們每次上線前都得手動把你之前添加的接口,挨個點一遍么,剛開始看著還能說過去,但是長遠看,效率太低。
這里我們在反過來看rest-assured,或者我們開發出一套適用于我們系統的測試框架,通常都是一句邏輯控制代碼加斷言,這樣一句簡單的代碼,的確能夠保證我們的產品質量,還能提升我們的工作效率。
到此,相信大家對“java的rest-assured怎么使用”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。