2

对 android 应用程序进行单元测试通常比预期的要困难,因为有些类没有公共构造函数(如 NotificationManager)和具有无法覆盖的方法的类,如 Context.getText。

对于 NotificationManager,我使用了委托人。我会对上下文做同样的事情,但这意味着在所有使用上下文(很多)的类中,我需要使用我自己的上下文,甚至不能从上下文派生。然后,每当我需要将上下文传递给 Android API 时,我都需要从我的包装器中获取真正的上下文。

它是否正确?还有另一种方法吗?将这些方法声明为 final 的理由是什么?是否有人真正为 Android 的大型应用程序编写过单元测试?

编辑

我找到了将 getText 方法定义为 final 的原因:它是一个模板方法。所以重写被调用的非最终方法就足够了

我也发现行得通,但有点奇怪

4

3 回答 3

2

问题有点模糊,所以我要写一个长答案。

有些类没有公共构造函数(如 NotificationManager)

因为有一些系统范围的资源/组件(例如 NotificationManager)Android 不喜欢应用程序按需构建/实例化,而是这些资源由系统集中和管理,应用程序应始终使用系统提供的 API 来获取它们.

以及具有无法覆盖的方法的类,例如 Context.getText

通常在 Java 中,标记为 final 的方法意味着它们受 API 保护,API 开发人员不希望应用程序开发人员覆盖默认行为。特别是对于 Context.getText() 这个方法,它实际上使用了模板方法模式,查看下面 herschel 的评论和源代码以获取更多详细信息。

那么问题是我们如何正确测试使用这些基于android上下文的资源/组件编写的代码?

Android SDK 给出的答案是测试项目(通过 InstrumentationTestRunner)。一般在使用 InstrumentationTestRunner 时,sense 背后,系统会同时安装 test.apk(从测试项目构建)和 app.apk(从应用项目构建),并使用 test.apk 操作 app.apk 进行测试。无论您使用 AndroidTestCase API(下图中称为 JUnit)还是​​ InstrumentationTestCase API(下图中称为 Instrumentation),都会发生这种情况相应的基于android上下文的可测试资源/组件(即Activity、NotificationManager或TextView)都是从实际运行的app.apk实例中获取的。如果您在测试项目中创建/使用自己的 MockContext,您可以从图中看到模拟对象被 InstrumentationTestRunner 注入到正在运行的应用程序中。

在此处输入图像描述

使用仪器测试的缺点在于效率,它进入了完整的运行生命周期(启动模拟器 -> 安装并启动 test.apk 和 app.apk 并触发 InstrumentationTestRunner),即使您只需要从单个方法测试单个方法类(正如你在评论中提到的)。我同意奥利的观点,这是一个敌对的设计。

这就是Robolectric发挥作用的地方,从他们的网站上引述:Robolectric 是一个单元测试框架,它去除了 Android SDK jar 的齿,因此您可以测试驱动您的 Android 应用程序的开发。测试在几秒钟内在您的工作站上的 JVM 中运行。

根据我自己的经验,我有一个应用程序包含大约 10 个活动和几个服务以及一些其他自定义视图/小部件,主要与远程服务器进行 http 通信,并使用仪器测试(通过测试项目)和 Robolectic 测试基于 Android 上下文的代码。只要时间允许,我几乎可以测试我的应用程序的几乎每一个类/公共方法。

于 2012-04-17T23:58:37.783 回答
0

Android 在很多方面都非常反对测试。

您可能想看看 Roboelectric http://pivotal.github.com/robolectric/

我假设你已经阅读了这些:

http://developer.android.com/guide/topics/testing/index.html

http://developer.android.com/resources/tutorials/testing/helloandroid_test.html

于 2012-04-17T16:20:26.750 回答
0

Android 为您提供的 *TestCase 类应该能够解决您遇到的测试问题。在大多数情况下,它会为您生成一个上下文,您可以根据需要覆盖该上下文。我建议从那里开始,或者询问有关如何测试一件事或另一件事的更具体的问题。

于 2012-04-17T16:21:59.220 回答