2011-09-12 243 views
11

我正在爲我的Android代碼編寫一些POJO測試。我想要在JDK本地運行它們(不適用於模擬器上的Dalvik) - 對於速度,JUnit 4,Mockito以及無需設備就可以運行無頭程序 - 因此我有一個單獨的「Java」項目蝕。使用JUnit和JDK測試Android代碼

如果我測試的方法恰好引用了Android SDK的任何內容,例如android.util.Log,測試失敗 - 這是有道理的,因爲android.jar不在類路徑中。要重現我有這樣的測試案例:

public class FooTests { 
    @Test 
    public void testFoo() { 
    android.util.Log.d("x", "y"); 
    } 
} 

如果我明確地添加android.jar到測試項目的類路徑,我得到這樣

java.lang.RuntimeException: Stub! 
    at android.util.Log.d(Log.java:7) 
    at com.example.FooTests.testFoo(FooTests.java:39) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    ... 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 

例外有沒有一種方法,使無嘲諷每代碼工作Android SDK依賴的最後一點?也許嘲笑android.jar已經存在?

編輯:現在我結束了包裝類,如android.util.Log並將它們注入的情況下,對經典的基於IOC的測試。當我需要時,Scott的PowerMock建議是我的下一步。

LATER EDITRobolectric

回答

3

我沒有嘲笑過android.jar,我知道。我使用Powermock來嘲笑一切。有一件事你可以做的,以幫助嚴重嘲弄的是讓你的擴展的Android類,如活動,片段,廣播等稀薄,並讓他們委託pojo類。你可以做一個基於風險的決定,不要孤立單元測試android擴展類,而是整合單元通過android測試框架或其他類似Robotium測試它們。

對於Android中真正的隔離單元測試,對於我來說,對java jvm進行單元測試嘲笑所有合作類是最好的方法。

+1

+1好點,我會嘗試PowerMock。除https://sites.google.com/site/androiddevtesting/之外的任何相關鏈接? – orip

+1

我之前沒有看到該鏈接,但它非常出色,感謝分享,當我試圖找出模擬android jar類所需的各種方法時,我發現自己經常在他們的網站上引用Powermock「usage」部分:http://code.google.com/p/ powermock /。 – Scott

0

不會the embedded android/junit tests做你想做的?

+4

到目前爲止,我已經使用它在模擬器或實際設備上使用InstrumentationTestRunner運行測試。當我想測試一個活動或一個服務時,而不是當我只想測試一些與Android平臺無關的普通舊邏輯時,這是適當的。我錯過了什麼嗎? – orip

+0

我認爲第一個項目符號會談論'簡單的老junit'測試,因爲你的'純粹的舊邏輯':) – KevinDTimm

+0

當然,但據我可以告訴我要麼必須在模擬器或設備上運行它們,要麼得到「Stub !」例外情況與現在相同:( – orip

4

我有同樣的問題。我想在本地測試簡單的POJO。
具體來說,我的代碼想使用android.util.Base64。
我最終做的是使用SDK來安裝Android 4源代碼,並將android.util.Base64類複製到我的項目中。令人驚訝的是,這工作。

+0

是的,我最終創建了一個「Base64Encoder」類型的接口,在應用程序中用'android.util.Base64'實現它,並在測試中用'sun.misc.BASE64Decoder'實現它:)它本來很棒簡單地擁有一個完整的庫代碼的JAR,以及與運行環境關聯的框架位被刪除。 – orip

2

我有同樣的問題。我想在本地測試簡單的業務邏輯。 具體來說,我的代碼使用android.util.SparseArray<E>

我嘗試了3種不同的方法,使它可以在android之外的junit上測試。

  • 在我的業務邏輯我創建了一個接口,並將其連接到MySparseArray<E>SparseArray<E>繼承。在junit-test中,我使用HashMap<Integer, E>重新實現了接口。這可以起作用,但從長遠來看,如果需要其他android.*,則需要做很多工作才能使業務邏輯可以進行單元測試。
  • 正如@Tal Weiss所建議的,我添加了所需類的android java源代碼:android.util.SparseArray.java,它使用了com.android.internal.util.ArrayUtils.java。這也適用,但我不喜歡添加更多的android資源,尤其是如果有更多的依賴關係
  • 我下載了一個免費的二進制android.jar舊版的android 2.2來自http://grepcode.com/snapshot/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1,並將它作爲lib包含在我的junit-java -項目。該jar僅包含命名空間android.*,com.android.*,dalvik.*framework.base.*的類。這也適用。

目前我成功避免使用我的業務層android.*類除外SparseArray<E>並沒有依賴於上下文,活動或服務。我可以在android-business層中使用HashMap<Integer, E>而不是SparseArray<E>

+0

我已經嘗試了https://github.com/bjoernQ/unmock-plugin在JUnit測試中使用SparseArray,它工作後,但添加keepStartingWith「dalvik.system」後。在unMock部分。 – Alexey