Android:使用Robolectric和Mockito对Android应用程序进行单元测试

Android:使用Robolectric和Mockito对Android应用程序进行单元测试,android,unit-testing,mockito,robolectric,Android,Unit Testing,Mockito,Robolectric,我有一个Java库,它使用了Android API中的一些东西。我想使用Mockito为这个库编写单元测试 有什么办法可以帮你吗 Mockito在Dalvik虚拟机上玩得不好,请参阅以下帖子: 更新: 自从这篇文章发表后,我发现了机器人分子,我有机会在Pivotal实验室工作,并对这个图书馆做出了一些小贡献。我建议在Android测试框架/mockito上使用它。此外,您可以自由使用Robolectric和Mockito,但是Robolectric中的阴影对象使得Mockito在大多数用例中都是

我有一个Java库,它使用了Android API中的一些东西。我想使用Mockito为这个库编写单元测试

有什么办法可以帮你吗

Mockito在Dalvik虚拟机上玩得不好,请参阅以下帖子:

更新:

自从这篇文章发表后,我发现了机器人分子,我有机会在Pivotal实验室工作,并对这个图书馆做出了一些小贡献。我建议在Android测试框架/mockito上使用它。此外,您可以自由使用Robolectric和Mockito,但是Robolectric中的阴影对象使得Mockito在大多数用例中都是不必要的

尝试对Android进行单元测试的问题在于,您构建的Android库中的每个方法都被存根清除,从而抛出存根异常或返回null。如果你想测试你的应用程序并想要任何Android行为,那你就太倒霉了,除非你使用Robolectric,它在类加载时动态重写字节码,并注入一个模拟该行为的阴影对象

更新2:

已经有一段时间了,事情发生了变化。Robolectric中的许多影子类已经被真正的Android类所取代。现在使用的是真正的Android JAR,而Robolectric只为小得多的东西加载影子类。这是在Android测试中使用Robolectric的更多原因。

看看。它基于EasyMock 2.4(因此没有Mockito那么好,但是很接近)

它绕过了DalvikVM的限制,在构建时而不是运行时预生成模拟类,然后在部署到设备时将它们与编译的测试代码绑定在一起


还有一个名为的模拟框架,我不能担保,但看起来很有希望(如果你愿意尝试让Scala在你的设备上运行的话)

对于与Android SDK内部类无关的所有内容,您都可以避免它。 这就是我为Android项目所做的(尽管我使用的是
JMock2
,而不是
Mockito

我有两个测试项目

  • 第一个使用我自己添加为依赖项的
    JUnit4
    JMock2
    。我测试所有的“业务逻辑”类,但我无法测试与Android有关的任何东西(UI类、SQLiteOpenHelper等)。如果我尝试在测试中使用它们,我会得到可怕的
    存根异常

  • 第二个是测试UI,使用
    ActivityInstrumentationTestCase2
    Robotium


这看起来可能需要很多工作和复杂,但事实并非如此,我实际上认为最好将它们分开。UI测试不是“真正的”单元测试,它们通常跨多个单元测试某些功能。如果您正确地将UI层与业务逻辑分离(并且这样分离测试将迫使您以TDD方式进行分离),那么这一切都很好且顺利。

在谷歌搜索了很多次之后,我找到了一个答案

基本上,它涉及到使用单元测试框架,它拦截了Android类的加载。然后,您可以继续使用Mockito(尽管在大多数情况下并不需要),并在JVM上运行测试

从1.9.5版(2012年6月3日发布)起,您可以在Android上使用Mockito。为此,您还需要dexmaker:

此wiki页面介绍了如何实现它:


是的,我知道那件事。如果不用的话,我会尽量避免使用它。Mockito上的语法要好得多。问题是,我的业务模型类使用AsyncTask获取我在应用程序中使用的每个页面上的每个数据片段。我在想,因为AsyncTask基本上是一个POJO,所以我可以抓取它的代码并将其放在我的项目中,然后失去依赖关系。如果我是你,我会尝试将所有Android依赖关系抽象到接口,这样存根就不会碍事。也许不像AsyncTask听起来那么简单…@Chirstopher Perry:你有没有找到有效测试异步任务的解决方案?我现在有点同舟共济了。这不会给你任何安卓行为。Robolectric仍然是最好的选择,因为它提供模拟(阴影类)和Android行为。我理解,但你的问题不是“什么是Android最好的模拟框架”,而是“我如何将Mockito与Android结合使用”。@Christopherry我想实际上可能会有一些混淆。以这种方式在Android测试框架和JUnit中使用Mockito意味着您的测试在实际设备或模拟器上运行,这意味着所有Android类都可用。Android测试框架还提供内置模拟,如
MockContext
。是的,但Android测试框架很糟糕。我更新了问题以反映整个主题。@Christopherry您已经更新了您的问题,而实际上您的编辑应该是一个单独的答案(因为它已经是)。这看起来很不礼貌。我使用Mockito提供的间谍构造和Robolectric提供的构建器相结合。这样,我可以在需要时对android组件进行部分模拟,例如FooActivity foo=spy(roblectric.buildActivity(FooActivity.class.get());doReturn(mock).when(foo).getSomething();