使用JUnit和JDK测试Android代码

使用JUnit和JDK测试Android代码,android,eclipse,junit,java,junit4,Android,Eclipse,Junit,Java,Junit4,我正在为我的Android代码编写一些POJO测试 我想用JDK(而不是模拟器上的Dalvik)在本地运行它们——为了速度,JUnit4,Mockito,并且能够在没有设备的情况下运行headless——所以我在Eclipse中有一个单独的“Java”项目 如果我正在测试的方法碰巧引用了Android SDK中的任何内容,例如,Android.util.Log,测试就会失败-这是有意义的,因为Android.jar不在类路径中。为了重现这个测试用例: public class FooTests

我正在为我的Android代码编写一些POJO测试

我想用JDK(而不是模拟器上的Dalvik)在本地运行它们——为了速度,JUnit4,Mockito,并且能够在没有设备的情况下运行headless——所以我在Eclipse中有一个单独的“Java”项目

如果我正在测试的方法碰巧引用了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建议是我需要的下一步


稍后编辑

不会做你想做的事吗?

据我所知,没有模仿过的android.jar。我使用Powermock来模拟一切。你们可以做的一件事是让你们的扩展android类,如activity、fragments、broadcasters等精简,并将它们委托给pojo类,这有助于解决严重的模拟问题。您可以做出基于风险的决定,不隔离单元测试android扩展类,而是通过android测试框架或其他类似Robotium的东西对它们进行集成单元测试


对于Android中真正的隔离单元测试,对我来说,在java jvm上模拟所有协作类进行单元测试是最好的方法

我也有同样的问题。我想在本地测试简单的POJO。
具体来说,我的代码想要使用android.util.Base64。
我最后做的是使用SDK安装Android 4源代码,并将Android.util.Base64类复制到我的项目中。

令人惊讶的是,这个方法奏效了。

我也有同样的问题。我想在本地测试简单的业务逻辑。 具体来说,我的代码使用了
android.util.SparseArray

我尝试了3种不同的方法使它在android之外的junit上可以测试

  • 在我的业务逻辑中,我创建了一个接口,并将其附加到继承自SparseArray的
    MySparseArray
    。在junit测试中,我使用
    HashMap
    重新实现了接口。这是可行的,但从长远来看,如果需要其他
    android.*
    ,要使业务逻辑单元可测试,这需要做很多工作
  • 根据@Tal Weiss的建议,我添加了所需类的android java源代码:
    android.util.SparseArray.java
    ,它使用
    com.android.internal.util.ArrayUtils.java
    。这也行得通,但我不喜欢添加更多的android源代码,特别是如果存在更多依赖项的话
  • 我从下载了一个旧安卓2.2版本的无存根二进制文件
    android.jar
    ,并将其作为lib包含在我的JUnitJava项目中。此jar仅包含名称空间
    android.*
    com.android.*
    dalvik.
    framework.base.*
    的类。这也行得通

目前,我成功地避免在我的业务层中使用
android.*
类,除了
SparseArray
,并且对上下文、活动或服务没有依赖性。我可以在android业务层中使用
HashMap
,而不是
SparseArray

卸载插件可能会有所帮助。在我的例子中,它与SparseArray一起工作。

到目前为止,我已经使用它在模拟器或实际设备上使用InstrumentationTestRunner运行测试。当我想测试一个活动或服务时,它是合适的,但当我只想测试一些与Android平台无关的普通老逻辑时,它就不合适了。我遗漏了什么吗?我想第一个要点是关于“普通老junit”测试,对于你的“普通老逻辑”:)当然,但就我所知,我要么必须在模拟器或设备上运行它们,要么得到与现在一样的“存根”异常:(+1点好,我会试试PowerMock。还有其他相关链接吗?我以前没见过这个链接,但非常好,谢谢分享。我发现自己引用了PowerMock的“用法”当试图找出模拟android jar类所需的各种方法时,他们网站上经常出现一个部分:。是的,我最终创建了一个“Base64Encoder”类型的界面,在应用程序中使用
android.util.Base64
,并在测试中使用
sun.misc.BASE64Decoder
实现:)如果一个JAR中的所有库代码都完好无损,并且只保留与运行环境相关的框架位,那就太棒了。我曾尝试在JUnit测试中使用SparseArray,但它成功了,但在unmack部分添加了keepStartingWith“dalvik.system.”之后。