2011-09-12 206 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