干貨!接口測試中模擬post四種請求數據


一、背景介紹

在日常的接口測試工作中,模擬接口請求通常有兩種方法,fiddler模擬和HttpClient模擬。

Fiddler是一個簡單的http協議調試代理工具,它界面友好,易于操作,是模擬http請求的利器之一。
而我們常說的HttpClient工具包,追根溯源是Apache基金的HttpComponent項目的一個組成部分。HttpComponent有三個主要組成部分,分別是HttpCore、HttpClient以及AsynchHttpClient。按照HttpComponent官網的介紹,HttpCore是底層的HTTP傳輸組件,用最小的內存來實現模擬客戶端和服務器端的Http請求。HttpClient則是基于HttpCore實現的Http請求模擬代理, 可以用來提供高效的、最新的、功能豐富的支持HTTP協議的客戶端編程工具包。Asynch HttpClient也是基于HttpCore的,顧名思義則是用于處理大量并發請求時的http代理。不同格式的數據通過這兩種模擬方法的處理方式不同。

在接口測試中,接口通常是get請求或者post請求。get請求的測試一般較為簡單,只需設置好相關的請求頭,url寫正確即可。但是在測試post請求時,請求數據格式的設置往往就稍顯復雜。尤其是在開發人員的接口文檔描述不清楚的情況下,會影響到測試效率。

故而本文總結了下post請求常見的四種數據格式和他們對應的fiddler、HttpClient模擬請求的構造方法。


二、post請求主體詳解

 一個正常的post請求主要包括請求行,請求頭,請求主體,也就是
 <method><url><version>
 <headers>
 <entity-body> 

對于get請求來說沒有請求主體entity-body。對于post請求而言,不會對發送請求的數據格式進行限制,理論上你可以發任意數據,但是服務器能不能處理就是另一回事了。服務器收到數據后,如何解析數據呢?它會以請求頭中的Content-Type設置的內容來進行數據解析。確定好Content-Type的格式之后,請求主體的數據格式也就確定下來了。Content-Type的格式有四種:分別是application/x-www-form-urlencoded(這也是默認格式)、application/json、text/xml以及multipart/form-data格式
這些不同的post請求數據格式要通過HttpEntity來構造,有必要簡單理一下HttpClient的HttpEntity對象,因為所有的post請求數據均需要置于HttpEntity實體中進行發送。HttpEntity是一個接口,實現這個接口的具體類有很多,比較常用的是StringEntity、UrlEncodedFormEntity(繼承自StringEntity)、MultipartEntity。他們將在發送不同格式的post請求時被用到。接下來就詳細地介紹每一種數據格式對應的fiddler請求模擬和httpClient請求模擬(java實現)的實現情況。


三、四種Post請求數據格式和fiddler和HttpClient模擬請求構造

(一)application/x-www-form-urlencoded數據格式

W3C官網上明確對這種數據格式進行了定義:
This is the default content type. Forms submitted with this content type must be encoded as follows:
Control names and values are escaped. Space characters are replaced by '+', and then reserved characters are escaped as described in [RFC1738], section 2.2: Non-alphanumeric characters are replaced by '%HH', a percent sign and two hexadecimal digits representing the ASCII code of the character. Line breaks are represented as "CR LF" pairs (i.e., '%0D%0A').The control names/values are listed in the order they appear in the document. The name is separated from the value by '=' and name/value pairs are separated from each other by '&'.

這是post請求最常見也是默認的數據提交格式。它要求數據名稱(name)和數據值(value)之間以等號相連,與另一組name/value值之間用&相連。例如:parameter1=12345&parameter2=23456。將請求的內容進行格式化了,其實這個方法同時簡化的客戶端發送,也簡化了服務器端獲取,服務器通過getParameters(String name)即可獲取到傳送來的信息。
我們看下如何分別用fiddler和HttpClient的話模擬post請求。
(1)如果用fiddler模擬請求的話,請求頭和請求主體的內容可以這樣構造:


模擬請求之后,從返回結果可以查看到我們的請求數據:


(2)如果用HttpClient模擬post請求的話,請求可以這樣構造:

DefaultHttpClient client = new DefaultHttpClient();
List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();     //定義鍵值對列表,用于存放向url發送post請求的數據。        
params.add(new BasicNameValuePair("parameter1", "12345"));        
params.add(new BasicNameValuePair("parameter2", "23456"));               //向params設置數據        
HttpPost post = new HttpPost("http://example.com");                      //定義HttpPost對象并初始化它    
HttpEntity reqEntity = new UrlEncodedFormEntity(params);                 //用UrlEncodedFormEntity對象包裝請求體數據                                                   
post.setEntity(reqEntity);                                               //設置post請求實體        
HttpResponse response = client.execute(post);                            //發送http請求        
System.out.println("the request body is:"+EntityUtils.toString(reqEntity));          //打印出請求實體        
System.out.println(response.getStatusLine().getStatusCode());                         //打印http請求返回碼

**(二)application/json數據格式 **
application/json格式的請求頭是指用來告訴服務端post過去的消息主體是序列化后的 JSON 字符串。
(1)如果用fiddler模擬請求的話,請求頭和請求主體的內容可以這樣構造:


模擬請求之后,從返回結果可以看到我們的請求數據:



(2)如果用HttpClient模擬post請求的話,請求可以這樣構造:

 HttpClient client = new DefaultHttpClient();   
 JSONObject js = new JSONObject();                                  //定義一個JSON數據格式對象,用其保存請求主體數據。
 js.element("parameter1", "12345");                                 //為JSON對象的各個key值賦值
 js.element("parameter2","23456");
 String postRequest = js.toString();
 HttpPost post = new HttpPost("http://example.com");                 //定義HttpPost對象并初始化它    
 StringEntity reqEntity = new StringEntity(js.toString());           //用StringEntity對象包裝請求體數據 
 reqEntity.setContentType("application/json");                       //設置請求頭數據傳輸格式 
 post.setEntity(reqEntity);                                          //設置post請求實體 
 HttpResponse response = client.execute(post);                       //發送http請求
 System.out.println("the request body is:"+EntityUtils.toString(reqEntity));            //打印出請求實體
 System.out.println(response.getStatusLine().getStatusCode());                          //打印http請求返回碼

這里我們可以發現HttpClient模擬post請求時,請求頭格式為application/x-www-form-urlencoded與application/json的主要差別在于請求主體的構造格式(前者是鍵值對,后者是JSON串)以及包裝請求體數據用的方法不同(前者是UrlEncodedFormEntity,后者是StringEntity)。
** (三)text/xml數據格式 **
(1)如果用fiddler模擬請求的話,請求頭和請求主體的內容可以這樣構造:


模擬請求之后,從返回結果可以看到我們的請求數據:


(2)如果用HttpClient模擬post請求的話,請求可以這樣構造:

Document doc = DocumentHelper.createDocument();                           //創建document對象
Element book = doc.addElement("book");                                    //構建document對象各個節點
book.addElement("title").addText("羋月傳");
book.addElement("author").addText("蔣勝男");
String body = book.asXML();                                               //Document對象轉成string類型
StringEntity reqEntity = new StringEntity(body);                          //用StringEntity對象包裝請求體數據
reqEntity.setContentType("text/xml");                                     //設置請求頭數據傳輸格式
reqEntity.setContentEncoding("utf-8");                                    //設置請求頭數據編碼格式
HttpPost post = new HttpPost("http://example.com");                       //定義HttpPost對象并初始化它   
post.setEntity(reqEntity);                                                //設置post請求實體
HttpResponse response = client.execute(post);                             //發送http請求
System.out.println("the request body is:"+EntityUtils.toString(reqEntity));   //打印出請求實體
System.out.println(response.getStatusLine().getStatusCode());                 //打印http請求返回碼

(四)multipart/form-data數據格式
除了傳統的application/x-www-form-urlencoded表單,我們另一個經常用到的是上傳文件用的表單,這種表單的類型為multipart/form-data。在HttpClient程序擴展包(HttpMime)中專門有一個類與之對應,那就是MultipartEntity類。此類同樣實現了HttpEntity接口。
(1)如果用fiddler模擬請求的話,請求頭和請求主體的內容可以這樣構造:
第一步,先設置好請求頭格式,然后點擊upload file...


第二步,上傳你的文件,這里我上傳一個png的圖片


這是fiddler根據我們上傳的文件自動調整生成的請求,在請求頭中看到,我們需要選擇一段數據作為“分割邊界”(boundary屬性),這個“邊界數據”不能在內容其他地方出現,一般來說使用一段從概率上說“幾乎不可能”的數據即可。每次post瀏覽器都會生成一個隨機的30-40位長度的隨機字符串,瀏覽器一般不會遍歷這次post的所有數據找到一個不可能出現在數據中的字符串,一般都是隨機生成。選擇了這個邊界之后,瀏覽器便把它放在Content-Type 里面傳遞給服務器,服務器根據此邊界解析數據。下面的數據便根據boundary劃分段,每一段便是一項數據。(每個field被分成小部分,而且包含一個value是"form-data"的"Content-Disposition"的頭部;一個"name"屬性對應field的ID等等,文件的話包括一個filename)
模擬請求之后,從返回結果可以看到我們的請求數據:

(2)如果用HttpClient模擬post請求的話,請求可以這樣構造:

HttpPost post = new HttpPost("http://example.com");           //定義HttpPost對象并初始化它
MultipartEntity mutiEntity = new MultipartEntity();           //定義MultipartEntity對象
File file = new File("C:\Users\hzsuixiang\Desktop\image_20151117151539.png");
mutiEntity.addPart("desc",new StringBody("網易云閱讀", Charset.forName("utf-8")));     //設置multiEntity對象的主體數據
mutiEntity.addPart("pic", newFileBody(file));post.setEntity(mutiEntity);             //設置post請求主體
HttpResponse  httpResponse = client.execute(post);                                   //執行post請求
HttpEntity httpEntity =  httpResponse.getEntity();                                   //獲得響應返回實體

綜上,就是接口測試中fiddler與HttpClient模擬post接口四種請求數據的構造方法,總結起來有利于在以后的接口測試工組過程中可以及時查閱。另外,為了盡可能簡化核心代碼,列出的這些代碼中并沒有寫出需要的jar包,大家使用的時候需要自行添加。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容