2012-09-26 90 views
1

我的代碼是API的使用者(www.abc.com/public/news/apple.json)。我得到一個json數組作爲回報,然後我解析並填充到自己的數據結構中。負責這樣做的代碼是:單元測試Web API消費模塊

public Map<String,List<NewsItem>> populateNewsArray() throws Exception 
     { 
      url = domain + newsApiStr; 
      InputStream stream = getNews(url, true); 

      //jackson library object mapper 
      ObjectMapper mapper = new ObjectMapper(); 

      //NewsApiObject class implements the structure of the json array returned. 
      List<NewsApiObject> mappedData = mapper.readValue(stream, NewsApiObject.class)); 

      //populate the properties in a HashMap. 
      //return HashMap 
    } 

    public InputStream getNews(String request, boolean bulk) throws Exception 
    { 
     URL url = new URL(request); 
     connection = (HttpURLConnection) url.openConnection();   
     connection.setDoOutput(true); 
     connection.setInstanceFollowRedirects(false); 
     connection.setRequestMethod("GET"); 
     connection.setRequestProperty("Content-Type", "text/plain"); 
     connection.setRequestProperty("charset", "utf-8"); 
     connection.connect(); 

     return connection.getInputStream(); 
    } 

正如你所看到的,我不是api的控制器,只有消費者。據說在單元測試中,不會假設發出http請求。在這種情況下,如何單元測試populateNewsArray()函數以查看對象映射是否正確(沒有任何例外)並返回有效的散列表?

回答

1

您應該將getNews()提取到單獨的界面中,例如,新聞閱讀(雖然單詞Reader已在JDK特定的含義,我喜歡這個名字......)

public interface NewsReader { 
    InputStream getNews(String request, boolean bulk) throws Exception 
} 

然後實現該接口使用HttpURLConnection按你的代碼和更新代碼,以允許特定的注射接口。然後,如果您需要測試代碼如何處理InputStream,則可以創建一個NewsReader的模擬,它會返回一個帶有衆所周知內容的InputStream

請記住要實現高內聚性:您的課程不應該是HTTP客戶端的流解析器。

+0

btw david,如果我確實爲新聞閱讀創建了一個接口,我仍然可以如何測試populateNewArray()函數?是否需要徹底更改該功能並刪除getNews調用,以便它可以進行單元測試? – samach

+0

@Salmanmahmood'populateNewArray'調用'NewsReader.getNews'。你可以注入一個模擬,它返回一個(例如)包含已知JSON的'ByteArrayInputStream'。 –

+0

我將如何確保模擬對象在測試時被調用,而不是真正的實現(網絡調用)? – samach

0

我會創建一個子類並覆蓋方法getNews(...)。在子類中,您可以返回InputStream進行測試。
既然你不應該在一個單元測試中依賴某個外部文件,並且爲了獲得更好的可測試設計,我還會更改getNews(...)方法以返回某種可以由映射器進一步處理的值。