熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java核心技術 >> 正文

用Java測試網絡代碼

2013-11-23 19:05:03  來源: Java核心技術 

  網絡代碼被證明是很難進行完全徹底的測試這是因為測試組件不依賴其他服務器以獨立進程形式工作時效果最好本文中Nelson Minar描述了兩種單元測試網絡代碼的方法首先他提出您設計網絡代碼時應該盡可能地做到邏輯上與網絡獨立接著他建議使用Java的協議處理器類模擬網絡連接而不是使用實際的網絡使用這些原則您就可以很輕松地生成網絡測試軟件
  測試網絡代碼並是一件很困難的事情優秀的單元測試組件運行速度非常快這樣開發人員在每次編譯之後就能夠進行測試當然測試流也要能夠穩定地運行這樣它們才可以持續捕獲代碼中的任何錯誤然而實踐證明網絡代碼(例如從URL上讀取的代碼)是很難快速並穩定地測試的而且如果測試組件本身進行網絡調用測試會因為依賴網絡和其他服務器將會變得非常緩慢並十分不穩定
  設想一個可以從網頁上下載格式化並顯示XML數據的程序該程序的本地測試流將需要從一個運行的Web服務器上獲取XML數據但是程序的很多部分——XML解析器格式化程序和顯示程序——可能不需要依賴網絡就可以獨立測試請記住這個例子我將在本文中舉例說明兩種可以測試與網絡相關代碼的方法當測試進行時這兩種方法可以避免使用網絡
  我首先描述簡單的網絡激活演示程序PrintRSS然後再討論如何使用簡單的 Reader 和Writer 對象而不是網絡連接來設計簡化測試的PrintRSS程序最後我將介紹一個允許程序員合成特殊的testurl庫使用正常http中的URLs繞過網絡注意 測試將使用JUnit 測試框架的 assert() 方法
  PrintRSS演示程序
  PrintRSS是一個可以從URL讀取數據並對數據進行處理的程序它可以很好的演示網絡代碼的測試PrintRSS 使用RSS格式讀取數據這個數據格式可以簡單地將新鮮內容並入XML本文中這個重要的RSS結構定義如下
  
   Channel Title
   Item <fp class='fp-qx8q6'></fp>
   Item <fp class='fp-zfw8j'></fp>
  

  PrintRSS從某個URL下載RSS文檔規定內容的具體布局然後以一種易讀的方式將標題輸出到Systemout
  Channel Title
   Item
   Item
  PrintRSS執行四個主要操作
  ● 打開與某一URL的連接
  ● 使用XML進行讀取
  ● 格式化數據
  ● 輸出到Systemout
  PrintRSS程序將上述的四種功能封裝在一個單獨的方法(printURL(URL))中然而很難對這個方法進行測試原因有兩個
  首先代碼依賴於從URL上讀取的數據如果URL 是一 URL這就要涉及到網絡而且輸出到Systemout所產生的影響使代碼自己的行為也被隱藏起來好好考慮一下這些問題您又能如何更好地設計Printress來進行測試呢?
  使用eaders和writers封裝數據
  簡單地解析和格式化XML代碼而不是連接網絡您就能分解代碼並獨立測試數據的邏輯性雖然再分解代碼看起來有點令人畏懼但是這樣的努力是為了得到更好的代碼這是因為代碼是經過測試的同時設計也更標准
  記住您可以將printURL()的代碼解析和格式化功能分解為一個新的方法formatReader(Reader Writer)這個方法專門用於對一個帶有XML數據的Reader對象進行解析然後將結果報告輸出到提供的Writer
  測試 formatReader(Reader Writer)現在變得簡單了
  testFormatReaderGoodData():
   String goodRSSData = +
   Channel Title +
   Item <fp class='fp-q90sp'></fp> +
   Item <fp class='fp-nenvc'></fp> +
  
;
   String goodRSSOutput = Channel Title\n Item \n Item \n;
  
   Reader r = new StringReader(goodRSSData);
   Writer w = new StringWriter();
   PrintRSSformatReader(r w);
  
   assertEquals(goodRSSOutput wtoString());
  上面的示例只用readers和writers在沒有URL和網絡連接的情況下測試了解析和格式化邏輯測試示例演示了一個有用的測試方法創建的reader流將測試數據包含在測試代碼中而不是從文件或者網絡讀取數據實踐證明StringReader和StringWriter(或者 ByteArrayInputStream 和ByteArrayOutputStream)在把測試數據嵌入到單元測試流方面是沒有價值的
  上述的單元測試在一切都正常時執行一定的邏輯進行觀察但它對問題出現錯誤處理代碼同樣重要接下來就是一個測試壞數據的示例其中巧妙的使用了Junit來檢查是否出現異常
  testFormatReaderBadData():
   String badXMLData = this is not valid xml data;
   StringReader r = new StringReader(badXMLData);
  
   try {
   PrintRSSformatReader(r new StringWriter());
   fail(should have thrown XML error);
   } catch (XMLParseException ex) {
   // No error we expected an exception
   }
  readers 和 writers再次封裝數據主要的不同在於這裡的數據使 formatReader()拋出異常如果沒有產生異常就會調用Junit的方法fail()
  使用Java 協議處理器測試網絡代碼
  雖然非網絡的分離方法可以使程序能像PrintRSS一樣易於測試但是這樣的努力對於創建完整的測試流還是不夠的我們仍希望測試網絡代碼本身尤其是網絡異常控制而且有時候分離到reader接口並不是很方便被測試的代碼可能會依賴於一個僅能理解URL的庫本部分我將解釋如何測試方法 formatURL(URL Writer)這種方法帶有URL讀取RSS並將數據輸出到writer
  您可以使用多種方式測試包含URL的代碼首先您可以使用標准 URLs 並指向運轉的測試服務器然而這種方法要求穩定的Web服務器——少一個組件來使測試復雜化其次您可以使用指向本地文件的 file: URLs這種方法和使 URLs存在相同的問題雖然您可以使用file:或者 URLs訪問准確的測試數據但是它仍然很難模擬導致I/O(輸入和輸出)異常的網絡失敗
  一個測試URL代碼的更好方法就是創建新的URL命名空間testurl:使之處於測試程序的完全控制之中——種使用Java協議處理器的簡單方法
  實現sturl
  Java協議處理器允許編程人員使用它們自己的代碼實現協議協議處理器很簡單
  首先滿足Java編寫協議處理器的需求要處理好三個重要的部分
  ● 類TTestURLConnection URLConnection的實現可以處理返回輸入流標題等實際方法
  ● 類 Handler 將testurl: URL轉換成 TestURLConnection
  ● 屬性javaprotocolhandlerpkgs 表示何處找到新的URL命名空間實現的系統屬性
  其次提供一個有用的TestURLConnection執行過程在這種情況下庫用戶看不到實際的 TestURLConnection 相反工作是通過類TestURLRegistry進行的這個類只有一個單獨的方法 TestURLRegistryregister(String InputStream)它將輸入流和給訂的URL聯系在一起例如
  InputStream inputIS = ;
   TestURLRegistryregister(data inputIS);
  如此安排使得開放的URL testurl:data返回inputIS中的輸入流實現了這一點您就能很容易的構建測試程序控制輸出的URL(注意輸入流數據並沒有復制因此通常情況下每一個URL您只能使用一次
   對准確數據的測試
  首先我們使用testurl用准確數據測試formatURL()
  
  testFormatURLGoodStream():
   InputStream dataIS = new ByteArrayInputStream(goodRSSDatagetBytes());
   TestURLRegistryregister(goodData dataIS);
   URL testURL = new URL(testurl:goodData);
  
   Writer w = new StringWriter();
   PrintRSSformatURL(testURL w);
   assertEquals(goodRSSOutput wtoString());
  上面的代碼和先前的測試使用相同的數據但這裡卻把數據與testurl:goodData URL聯系起來方法formatURL() 打開並讀取URL測試代碼保證數據能夠正確讀取格式化並被輸出到Writer
  模擬失敗
  用網絡環境編寫程序很容易但編寫可以正確處理網絡失敗的代碼卻比較困難testurl能夠模擬網絡失敗——這是該方法的主要優點
  首先模擬連接到某一URL的網絡失敗是不可能的這種情形的一個典型代表就是遠程web服務器沒有工作我們的testurl:庫包含一個它能理解的URLtestlurl:errorOnConnect 將保證只要您連接到這個URL它就會拋出一個IOException您可以使用這個URL並對程序是否能正確處理URL不能訪問的情況進行測試
  testFormatURLNoConnection():
   URL noConnectURL = new URL(testurl:errorOnConnect);
   Writer w = new StringWriter();
   try {
   PrintRSSformatURL(noConnectURL w);
   fail(Should have thrown IO exception on connect);
   } catch (IOException ioex) {
   }
  如果連接失敗上面的測試保證formatURL()可以正確地拋出一個IOException但是您將如何測試這樣一種情形(起初網絡連接正常工作但在交互期間失敗)呢?
  因為您已經完全控制了與測試URL相關的輸入流您就可以選用任意一種輸入流實現例如您創建一個簡單的類BrokenInputStream它用方法read()封裝輸入流而方法read()在拋出異常IOException之前只允許讀取一定字節數目的數據
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26243.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.