使用 JUnit 和 JDK 测试 Android 代码

发布于 2024-12-04 07:22:12 字数 1102 浏览 0 评论 0 原文

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

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

如果我正在测试的方法碰巧引用了 Android SDK 中的任何内容,例如 android.util.Log,则测试失败 - 这是有道理的,因为 android.jar 不是“ t 在类路径中。为了重现我有这个测试用例:

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 建议是我需要时的下一步。

稍后编辑Robolectric

I'm writing some POJO tests for my Android code.

I want to run them locally with the JDK (not with Dalvik on the emulator) - for speed, JUnit 4, Mockito, and being able to run headless without a device - so I have a separate "Java" project in Eclipse.

If the method I'm testing happens to reference anything from the Android SDK, e.g. android.util.Log, the test fails - this makes sense because android.jar isn't in the classpath. To reproduce I have this test case:

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

If I add android.jar explicitly to the test project's classpath, I get exceptions like

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)

Is there a way to make the code work without mocking out every last bit of Android SDK dependency? Perhaps a mocked-out android.jar already exists?

EDIT: For now I ended up wrapping classes like android.util.Log and injecting them into the instances, for classic IOC-based testing. Scott's PowerMock suggestion is my next step when I'll need it.

LATER EDIT: Robolectric!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

叹沉浮 2024-12-11 07:22:12

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

I had the same problem. I wanted to test simple POJOs locally.
Specifically, my code wanted to use android.util.Base64.
What I ended up doing was to use the SDK to install the Android 4 sources, and copied the android.util.Base64 class to my project.
Surprisingly enough, this worked.

微凉徒眸意 2024-12-11 07:22:12

据我所知,没有模拟的 android.jar 。我使用 Powermock 来模拟一切。为了帮助处理繁重的模拟,您可以做的一件事是使您的扩展 Android 类(如 Activity、Fragment、Broadcasters 等)变薄,并让它们委托给 pojo 类。您可以做出基于风险的决定,不对 Android 扩展类进行隔离单元测试,而是通过 Android 测试框架或其他类似 Robotium 的工具对它们进行集成单元测试。

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

There's no mocked out android.jar that I know of. I use Powermock to mock everything out. One thing you can do to help with the heavy mocking is to make your extended android classes like activity, fragments, broadcasters, etc. thin and have them delegate to pojo classes. You could make a risk based decision not to isolation unit test the android extended classes, and instead integration unit test them via the android testing framework or something else like Robotium.

For true isolation unit testing in Android, for me unit testing on the java jvm mocking all out all collaborating classes is the best way to go.

不…忘初心 2024-12-11 07:22:12

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

我尝试了 3 种不同的方法来使其可以在 android 之外使用 junit 进行测试。

  • 在我的业务逻辑中,我创建了一个接口并将其附加到继承自 SparseArrayMySparseArray。在 junit-test 中,我使用 HashMap 重新实现了接口。这是可行的,但从长远来看,如果需要其他 android.* ,那么要使业务逻辑可进行单元测试,这需要做很多工作。
  • 按照@Tal Weiss的建议,我添加了所需类的android java源:使用com.android.internal.util.ArrayUtils.javaandroid.util.SparseArray.java >。这也有效,但我不喜欢添加更多的 android 源,特别是如果有更多的依赖项,
  • 我从 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.* 的类。这也有效。

目前,我成功地避免在业务层中使用除 SparseArray 之外的 android.* 类,并且不依赖于 Context、Activity 或 Service。我可以在 android-business 层中使用 HashMap 而不是 SparseArray

I had the same problem. I wanted to test simple business logic locally.
Specifically, my code uses android.util.SparseArray<E>.

I tried 3 different approaches to make it testable with junit outside android.

  • In my business logic I created an interface and attached it to MySparseArray<E> that inherits from SparseArray<E>. In the junit-test I re-implemented the interface using HashMap<Integer, E>. This works but in the long run this is to much work to make business logic unit-testable if other android.* are required.
  • As suggested by @Tal Weiss I added the android java sources of the required classes: android.util.SparseArray.java that uses com.android.internal.util.ArrayUtils.java. This works, too but I don't like to add more android sources, especially if there are much more dependencies
  • I downloaded a stub free binary android.jar for an old android 2.2 from http://grepcode.com/snapshot/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1 and included it as lib into my junit-java-project. This jar contains only classes for namespaces android.*, com.android.*, dalvik.* and framework.base.*. This works too.

Currently I succeeded to avoid using android.* classes except SparseArray<E> in my business layer and has no dependency to Context, Activity or Service. I could have used HashMap<Integer, E> in the android-business layer instead of SparseArray<E>.

冷月断魂刀 2024-12-11 07:22:12

unmock-plugin 可以帮助 https://github.com/bjoernQ/unmock-plugin。就我而言,它适用于 SparseArray。

unmock-plugin could help https://github.com/bjoernQ/unmock-plugin. In my case it works with SparseArray.

原野 2024-12-11 07:22:12

嵌入式 android/junit 测试不会做你想要的吗?

Won't the embedded android/junit tests do what you want?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文