java的rest-assured怎么使用

本篇內(nèi)容主要講解“java的rest-assured怎么使用”,感興趣的朋友不妨來看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“java的rest-assured怎么使用”吧!

專注于為中小企業(yè)提供成都做網(wǎng)站、成都網(wǎng)站設(shè)計(jì)、成都外貿(mào)網(wǎng)站建設(shè)服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)烏蘭察布免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動(dòng)了上千企業(yè)的穩(wěn)健成長(zhǎng),幫助中小企業(yè)通過網(wǎng)站建設(shè)實(shí)現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。

 關(guān)于rest-assured
rest-assured 是一個(gè)能夠簡(jiǎn)化測(cè)試rest服務(wù)的Java DSL,像ruby或者python一樣的動(dòng)態(tài)語言去測(cè)試和驗(yàn)證http服務(wù)。基于java并且兼容了groovy動(dòng)態(tài)語言的特性,使我們像寫腳本語言一樣去測(cè)試http服務(wù)。

例如:你的http服務(wù)( http://localhost:8080/lotto/{id})返回一個(gè)如下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]
         }
      ]
   }
}

很簡(jiǎn)單的使用rest-assured斷言你的響應(yīng)結(jié)果是否符合預(yù)期。

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

或者你想斷言下 winnerId是不是 23 和 54:
get("/lotto").then().body("lotto.winners.winnerId", hasItems(23, 54));

如果看起來很簡(jiǎn)單,have a try?

rest-assured小試牛刀
在我們沒有運(yùn)行測(cè)試用例之前,我們需要把**rest-assured**的maven依賴先引入

<dependency>
    <groupId>io.rest-assured</groupId>
    <artifactId>rest-assured</artifactId>
    <version>3.0.0</version>
    <scope>test</scope>
</dependency>

RestAssured這個(gè)類是整個(gè)測(cè)試框架的請(qǐng)求入口,類的內(nèi)部定義了一系列靜態(tài)方法,包括我們常用的POST, GET, PUT, DELETE, OPTIONS, PATCH and HEAD等請(qǐng)求類型,請(qǐng)求響應(yīng)結(jié)果
能用于我們常用的驗(yàn)證和斷言。

RestAssured.get方法請(qǐng)求http服務(wù)

Response response = RestAssured.get("http://localhost/greting?id=5");

請(qǐng)求響應(yīng)結(jié)果response中定義了一系列的json轉(zhuǎn)換方法,你可以很簡(jiǎn)單把你的結(jié)果轉(zhuǎn)換成
json等字符串直接輸出

response.asString();

或者對(duì)應(yīng)實(shí)體bean轉(zhuǎn)換為json對(duì)象或者xml。

//json
GreetingBean as = response.as(GreetingBean.class);
//xml
XmlPath xmlPath = response.xmlPath();

也可以把返回結(jié)果進(jìn)行驗(yàn)證是不是你想要的結(jié)果

response.then().statusCode(200).body("name",equalTo("test"));

看到這里你可能認(rèn)為**rest-assured**提供的方法的確很簡(jiǎn)單,但是我把httpclient或者
okhttp封裝一下,也可以達(dá)到這個(gè)效果,我是一個(gè)程序員,我就是喜歡重復(fù)造輪子,因?yàn)檫@樣才可以提高我自己的編程水平,那么OK,你一定要造一個(gè)比它還好用的輪子。
對(duì)于上面的http測(cè)試請(qǐng)求還是可以在簡(jiǎn)化,能用小程序?qū)崿F(xiàn)的,決不用大程序。

第一步:

import static io.restassured.RestAssured.given;

第二步:

get("http://localhost/greting?id=5")

我們就可以使用簡(jiǎn)單的get,post或者delete發(fā)送我們的請(qǐng)求,并且可以獲得響應(yīng)結(jié)果進(jìn)行斷言返回結(jié)果是否正確。
雖然我們?cè)谑褂脛e人東西,但是我們也要知其然知其所以然,刨根問底。如果你足夠仔細(xì),打開源碼一識(shí)真面目,其實(shí)你會(huì)發(fā)現(xiàn)**rest-assured**本身也沒有什么神秘,他就是充分利用了java多態(tài)的特性,對(duì)接口進(jìn)行了高度的繼承和封裝。查看get或者post等一系列http請(qǐng)求方法的實(shí)現(xiàn),你會(huì)發(fā)現(xiàn)所有的請(qǐng)求體Request,rest-assured本身都對(duì)他進(jìn)行了重新定義,即RequestSpecification,這只是一個(gè)接口,它的實(shí)現(xiàn)類則是TestSpecificationImpl,這里面則是封裝了標(biāo)準(zhǔn)的http請(qǐng)求(如下,截取了其中的一部分,來自于類io.restassured.internal.TestSpecificationImpl),它是使用groovy語言進(jìn)行實(shí)現(xiàn)。


 /**
   * {@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虛擬機(jī))的敏捷開發(fā)語言,它結(jié)合了Python、Ruby和Smalltalk的許多強(qiáng)大的特性,Groovy 代碼能夠與 Java 代碼很好地結(jié)合,也能用于擴(kuò)展現(xiàn)有代碼。

你可以再反過來看看返回結(jié)果response也是按照這種思路,里面也有一個(gè)實(shí)現(xiàn)類即ResponseSpecificationImpl。這里也就契合了為什么一開始我們?yōu)槭裁凑frest-assured是基于java DSL(*DSL是一種為了特定任務(wù)而設(shè)計(jì)的開發(fā)語言* )框架。

 rest-assured優(yōu)勢(shì)
* 足夠簡(jiǎn)單,短,而且編寫測(cè)試用例快(*應(yīng)該是程序員為啥找不到女朋友的原因吧*)。
* 順序控制結(jié)構(gòu)(*最簡(jiǎn)單的結(jié)構(gòu)莫過于此,執(zhí)行這條語句然后執(zhí)行下一條語句的形式*)
* 符合契約編程思想(*如果前置條件滿足的情況下調(diào)用函數(shù),那么函數(shù)的執(zhí)行將確立后置條件*)

rest-assured系統(tǒng)測(cè)試

耐心看了上面的內(nèi)容,相信你對(duì)這個(gè)測(cè)試框架有了個(gè)整體的了解,但是在現(xiàn)實(shí)場(chǎng)景中根本不可能使用java的main函數(shù)直接調(diào)用RestAssured里面的靜態(tài)函數(shù),因?yàn)檫@樣寫出來的測(cè)試用例是不容易維護(hù)的,也是不可移植的,因?yàn)檫@些測(cè)試用例今天你是簡(jiǎn)單在打包前跑了下測(cè)試用例,確定沒有錯(cuò)誤后,打成測(cè)試包,但是之后可能也對(duì)這個(gè)產(chǎn)品進(jìn)行持續(xù)集成(CI server或者jenkins等),又或者這個(gè)產(chǎn)品的用戶量比較大我們需要在Jmeter或者loaderunner中,跑下腳本,測(cè)試性能。這時(shí)我們要把*rest-assured*結(jié)合*Junit*(或者一些自己擅長(zhǎng)的單元測(cè)試框架testNG等)進(jìn)行使用。

下面簡(jiǎn)單介紹下幾種常見的測(cè)試用例場(chǎng)景:
第一步,確保你已經(jīng)引入Junit和rest-assured包。
并且在引入類的同時(shí)進(jìn)行靜態(tài)化,如下:

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的注解,在運(yùn)行測(cè)試用例之前的準(zhǔn)備工作。這里我們配置了ip地址和端口。看到這里有的同學(xué)可能要問了我的請(qǐng)求是基于https單向請(qǐng)求,那么我們可以在setup函數(shù)中添加 :

`RestAssured.config.getSSLConfig().relaxedHTTPSValidation();`
這個(gè)設(shè)置代表信任所有客戶端,不用攜帶任何可信任證書,直接能夠請(qǐng)求到服務(wù)端,如果這時(shí)你使用OKHttp或者h(yuǎn)ttpURLConnection,你可能就要花時(shí)間自己實(shí)現(xiàn)繞過https認(rèn)證了,可能你現(xiàn)在手頭有一份可信任證書,想要模擬真是的瀏覽器環(huán)境,你可以這樣設(shè)置:

RestAssured.config.getSSLConfig().trustStore("test.truststore","123456");

我曾經(jīng)自己原生的java語言以及httpclient實(shí)現(xiàn)過基于證書的雙向認(rèn)證過程[具體請(qǐng)查看源碼](https://github.com/strictnerd/LearningSummary/tree/master/src/main/java/com/clq),已經(jīng)精簡(jiǎn)到不能在精簡(jiǎn),還寫了個(gè)大概十行左右的代碼,如果不參考之前寫的,我可能還要翻開API看看到底是怎么調(diào)用的。但是rest-assured就跟我們做了很好的封裝如下:

RestAssured.certificate("clq.truststore", "123456","clq.p12", "123456", CertificateAuthSettings.certAuthSettings().keyStoreType("PKCS12").trustStoreType("jks"));

因?yàn)榇a的封裝不夠好,降低了我們的工作效率,很明顯rest-assured提高了我們的工作效率,降低了我們?cè)诠ぷ髦锌赡艹鲥e(cuò)的機(jī)率。
其實(shí)它這里面不僅做了單雙向認(rèn)證的封裝,我們平時(shí)常見的用戶名密碼登錄、oauth認(rèn)證、代理請(qǐng)求等等。

第二步,開始我們的rest服務(wù)測(cè)試

get請(qǐng)求測(cè)試


@Test
public void greetingTest() {
    given().param("name", "clq")
            .then().statusCode(200)
            .body("id", equalTo(2),"content", containsString("Hello"))
    .when().get("/greeting");
}

這一大串的順序控制結(jié)構(gòu)代碼的含義就是,給出參數(shù)name,當(dāng)我發(fā)送get請(qǐng)求之后,那么你給我返回響應(yīng)碼200,并且id=2,content為hello。
如果你的這個(gè)rest服務(wù)請(qǐng)求測(cè)試有一定的特殊性,那么你可以在這個(gè)測(cè)試用例中進(jìn)行另外的聲明。如下:


@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里面進(jìn)行reset,因?yàn)橛锌赡軙?huì)影響其它的測(cè)試用例。同樣的我們舉一個(gè)基于json請(qǐng)求的post實(shí)例,(這個(gè)框架可不僅支持基于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");
}


這個(gè)post請(qǐng)求,我在這里設(shè)置了特別多的場(chǎng)景,首先是requestBody里面的json傳參,并且使用代理192.168.1.11:2010,當(dāng)我發(fā)送post請(qǐng)求后,那么給我返回響應(yīng)碼200,body里面的結(jié)果符合預(yù)期(里面內(nèi)置了hamcrest這個(gè)包,它的主要作用是response返回結(jié)果進(jìn)行驗(yàn)證)。這些場(chǎng)景也是比較常見的,比如說,我的后臺(tái)要添加一個(gè)這樣的功能,支持微信公眾號(hào)服務(wù)的調(diào)用,但是我的整個(gè)后臺(tái)服務(wù)都是部署在內(nèi)網(wǎng),只有微信調(diào)用微信公眾號(hào)獲取openid的這一部分需要使用外網(wǎng),于是搭建了一個(gè)外網(wǎng)的代理服務(wù)器,那么我就可以基于http請(qǐng)求的代理服務(wù),只讓這部分rest服務(wù)訪問外網(wǎng)。

我們現(xiàn)實(shí)場(chǎng)景中還有一些經(jīng)常使用的像文件上傳和下載之類的,它也是支持的。

文件上傳,并且在上傳文件的同事支持參數(shù)的傳遞。

@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使用場(chǎng)景
我的系統(tǒng)測(cè)試非常復(fù)雜,有基于表單的,基于json數(shù)據(jù)格式的,還有使用了xml格式,有部分返回的數(shù)據(jù)結(jié)構(gòu)也很復(fù)雜,有的接口請(qǐng)求地址或者端口是不一樣的,或者使用了代理等功能。

你可以直接使用rest-assured來解決你碰到的這些實(shí)際問題。

我是不是可以在業(yè)務(wù)代碼的請(qǐng)求中直接使用rest-assured?

其實(shí)這個(gè)我是不推薦的,因?yàn)槲以?jīng)在我機(jī)器上,基于我自己的系統(tǒng)對(duì)rest-assured和httpclient做了比較,分別單線程測(cè)試(*分別請(qǐng)求1000次,rest-assured耗時(shí)85s,httpclient耗時(shí)79s*)后來我自己也做過多線程測(cè)試,無論怎么測(cè)試,得出的結(jié)論就是httpclient也比rest-assured快。當(dāng)然這個(gè)可能也不一定準(zhǔn)確,服務(wù)不同環(huán)境不同,測(cè)試結(jié)果也會(huì)隨之改變。畢竟rest-assured底層對(duì)httpclient又進(jìn)行了一次封裝,而且使用了groovy,groovy雖然是一門動(dòng)態(tài)語言,但是他還是基于jvm平臺(tái)的,最后還是編譯成了class。個(gè)人認(rèn)為,groovy除了在jvm平臺(tái)上執(zhí)行,并且寫的腳本足夠短之外,跟其它的ruby或者python等腳本語言相比,是沒有什么優(yōu)勢(shì)的。但是他作為測(cè)試用例來用,優(yōu)勢(shì)還是非常大的,因?yàn)闇y(cè)試用例,不是線上環(huán)境,對(duì)性能沒什么特別要求。

 我使用了springmvc Controller可以使用rest-assured做接口測(cè)試嗎?

其實(shí)對(duì)于這個(gè)rest-assured也有對(duì)應(yīng)的spring-mock-mvc,但是spring官方也有基于spring-test接口測(cè)試,要是還用rest-assured提供的,老感覺有一種拿著錘子找釘?shù)母杏X。

測(cè)試帶給我們的好處
測(cè)試給我們的產(chǎn)品帶來的好處是非常多的,這里我們只是基于rest API進(jìn)行測(cè)試,在單元測(cè)試中來說,這是一個(gè)粗粒度的測(cè)試,如果想更加詳細(xì),像基于h3數(shù)據(jù)庫的腳本測(cè)試,但是現(xiàn)在我們大部分框架都使用了jpa,這個(gè)測(cè)試能給我們帶來一定好處,但是工作量也是很可觀的,該不該進(jìn)行一些基于h3內(nèi)存數(shù)據(jù)庫的模擬測(cè)試,這里我們自己拿捏,不做過多的建議。至于基于mock業(yè)務(wù)邏輯的隔離測(cè)試,當(dāng)我們碰到復(fù)雜業(yè)務(wù)邏輯,或者在某種環(huán)境下,某個(gè)場(chǎng)景難于模擬,如果我們使用了mock,這種場(chǎng)景完全可以避免掉。這種測(cè)試該做還是要做的,下面我們可以簡(jiǎn)單說下單元測(cè)試本身給我們帶來哪些明面上的好處。

 首先應(yīng)該就是它是一種驗(yàn)證行為,而且具有一定的可回歸性。

我們只是在每完成一個(gè)功能之后寫了一個(gè)測(cè)試用例,立刻可以驗(yàn)證我們的功能是通過的。當(dāng)我們的一個(gè)模塊或者一個(gè)大的功能通過之后,我們可以基于maven快速的運(yùn)行所有的單元測(cè)試。來保證我們的功能在本地是通過測(cè)試的。其實(shí)就是在開發(fā)后期,我們看著某一塊功能或者業(yè)務(wù)邏輯很不爽(這是別人寫的),那么我們就可以直接修改功能或者重構(gòu),之后我們就可以利用測(cè)試用例來保證沒有破壞其他的設(shè)計(jì),說白了單元測(cè)試能給我們改善設(shè)計(jì)帶來信心。

單元測(cè)試代碼更具有可維護(hù)性,在某種程度上,可以認(rèn)為是一種文檔的行為,但是帶來效果可能比文檔還要好。

一套系統(tǒng),我開發(fā)出來,可能過幾天交給AA了,2年后交給了CC,CC怎么才知道后臺(tái)服務(wù)系統(tǒng)是完全沒有問題的,或者說他怎么知道某個(gè)rest服務(wù)的目的是什么。如果說我們測(cè)試用例中寫了完整的輸入和輸出的斷言機(jī)制,整體系統(tǒng)的代碼可讀性都會(huì)增強(qiáng)。

 能夠在某種程度上提升代碼質(zhì)量。

這一點(diǎn)我也認(rèn)為是非常重要的,當(dāng)你編寫完一個(gè)簡(jiǎn)單的功能時(shí),你運(yùn)行一下,輸入一些邊界條件,保證程序是可運(yùn)行的。這一點(diǎn)是必須的,但是當(dāng)你出現(xiàn)問題,通常我們調(diào)試代碼的過程都是打個(gè)斷點(diǎn),進(jìn)入代碼內(nèi)部進(jìn)行詳細(xì)分析,這時(shí)你對(duì)你的剛剛完成的業(yè)務(wù)邏輯有個(gè)整體的認(rèn)識(shí),這時(shí)如果你發(fā)現(xiàn)有不合適的地方,或者代碼冗余的地方,你應(yīng)該開始調(diào)整了。特別是當(dāng)你使用mock進(jìn)行隔離測(cè)試時(shí),有時(shí)為了測(cè)試某一個(gè)場(chǎng)景,你不得不解耦合(因?yàn)檫@樣讓你更容易測(cè)試),在不知不覺中提升了自己的代碼質(zhì)量。

當(dāng)然上述都是一些單元測(cè)試的好處,測(cè)試本來都應(yīng)該是軟件開發(fā)的一部分,這些都是不可否認(rèn)的。甚至有人提出了TDD,先編寫測(cè)試用例,測(cè)試用例來確定要編寫什么產(chǎn)品代碼,這些都充分說明了單元測(cè)試的重要性。

所以我們不僅要寫測(cè)試用例,還要寫好測(cè)試用例。

系統(tǒng)測(cè)試覆蓋率依然少的可憐?

其實(shí)究其原因無非就是產(chǎn)品更新迭代快需要快速占領(lǐng)市場(chǎng),或者項(xiàng)目趕得實(shí)在太緊急,根本沒有時(shí)間寫測(cè)試用例,這里一般都是說沒有時(shí)間寫測(cè)試用例,但是還是要測(cè)試的。我感覺除了一些業(yè)界大牛外,在自己的一段業(yè)務(wù)代碼沒有做測(cè)試前,誰敢保證完全沒有任何問題。再說業(yè)界大牛估計(jì)寫業(yè)務(wù)代碼的也不多吧。所以我經(jīng)常就發(fā)現(xiàn)一些現(xiàn)象就是,大部分人在這種情況下,對(duì)于rest服務(wù)接口,直接簡(jiǎn)單省事的用一個(gè)httpURLconnection輪番測(cè)試所有的接口,最后測(cè)著測(cè)著自己的測(cè)試代碼都有問題了,這還如何保證自己服務(wù)端代碼的質(zhì)量呢?有的同學(xué)可能比較擅長(zhǎng)使用一些工具,像谷歌的postman或restclient等http接口測(cè)試工具,直接把請(qǐng)求拷貝過去,參數(shù)添加上去,運(yùn)行下,OK!有些運(yùn)用熟練地同學(xué)發(fā)現(xiàn)里面還可以收藏,把你以前添加的接口收藏到一個(gè)列表中,以后可以繼續(xù)使用。在某種程度上來說,他提高了我們一些效率,但是難道我們每次上線前都得手動(dòng)把你之前添加的接口,挨個(gè)點(diǎn)一遍么,剛開始看著還能說過去,但是長(zhǎng)遠(yuǎn)看,效率太低。

這里我們?cè)诜催^來看rest-assured,或者我們開發(fā)出一套適用于我們系統(tǒng)的測(cè)試框架,通常都是一句邏輯控制代碼加斷言,這樣一句簡(jiǎn)單的代碼,的確能夠保證我們的產(chǎn)品質(zhì)量,還能提升我們的工作效率。

到此,相信大家對(duì)“java的rest-assured怎么使用”有了更深的了解,不妨來實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

網(wǎng)站名稱:java的rest-assured怎么使用
文章地址:http://muchs.cn/article34/ipiepe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供商城網(wǎng)站Google、ChatGPT網(wǎng)站設(shè)計(jì)、營(yíng)銷型網(wǎng)站建設(shè)網(wǎng)站策劃

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)公司