測試與API互動的HTTP調用是一件令人生厭的複雜事情。測試一個真實的Web伺服器時,一大堆問題随之産生:脆性測試(brittle test,因為網絡或API本身的問題而導緻的測試失敗)、速度減慢測試(slow test,每一次HTTP調用都要花費好幾秒)和不完全測試(“如何觸發一個速率限制越界用例?想一想,我隻希望速率限制會起作用……”)。
像Android這樣的平台HTTP理應是異步調用,問題會變得更加複雜。如果在這些測試組合中添加計時器,那麼你就準備好在測試API調用上認輸吧。
解決這些問題并且練習這些HTTP調用的一個絕妙方法是,使用一個很好的
Mockito (一個Java測試雙庫 double library)通用程式: ArgumentCaptor。
ArgumentCaptor與混合測試雙有幾分相似;有點類似存根(stub),也有點類似偵聽程式(spy),但不完全是其中任何一個。可以使用參數捕獲器捕獲并存儲傳給mock/stub的參數。然而這裡真正的亮點是對捕獲的參數進行方法調用,對于像
Retrofit回調有很大幫助。
譯注:Retrofit是一個Android & Java的類型安全REST用戶端。
有了Retrofit,我們可以發起一個API調用并提供一個回調方法。當伺服器做出響應時,Mockito會使用響應資料執行回調方法。
下面這些代碼使用
Github API 查詢使用者代碼倉庫: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | |
這裡有三個我們想要測試的用例:理想路徑(happy path,擷取一些代碼倉庫并把傳遞給擴充卡)、錯誤路徑(error path,向使用者提示伺服器錯誤)、特殊用例(special case, 向使用者提示沒有代碼倉庫錯誤)。
如果你的測試依賴于在真實的API伺服器,那麼第二和第三個用例會很複雜。我了解到最近GitHub有一些DDOS問題,但你肯定不能依賴它們來測試你的錯誤用例!
然而我們可以通過ArgumentCaptor捕獲回調參數,進而完全控制發送的資料。
看一下對理想路徑的測試(我用的是
Robolectri,建議你也嘗試一下):
|
captor(cb)捕獲到回調,調用getValue()方法以後,通過success方法向它傳遞一些僞對象(dummy object)。
你可能會感歎“啊哈(原來可以這麼簡單)”。呵呵,如果沒有也沒關系。接下來可以看一下對錯誤路徑的測試:
|
像之前一樣,我們捕獲了回調。但是這一次我們調用了failure方法,它模拟了一個API錯誤。如果我們需要更有針對性的錯誤處理(例如:如果傳回狀态是401,就重定向再登陸;如果是500, 彈出一條普通的系統錯誤消息),可以通過建立合适RetrofitError對象作為failure調用的參數。
目前為止,ArgumentCaptor的威力真的很贊。我們完全控制了捕獲到的對象,并且能夠給這些對象設定任意的資料或者觸發任意想要測試的錯誤。
為了讓内容更加豐富,下面是對一個特殊用例的測試:
|
(你可以在
GitHub上找到示例的全部源碼和工程檔案)。
有一個特殊細節要注意:如果在聲明捕獲器時使用了Mockito注解,
|
請確定在設定中的某個地方添加了下面代碼:
|
這種測試方法完全符合書中提到的所有特點:快速、健壯、易于使用。我們還可以通過它很容易地測試項目中很少出現的邊緣情況(會話逾時、伺服器維護、特殊值),確定我們的應用正常運作。
雖然本文示例是專門針對某種棧(Android、Robolectric、Retrofit、Mockito),但是類似的方法幾乎适用于任何應用。