问题有点模糊,所以我要写一个长答案。
有些类没有公共构造函数(如 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 上下文的代码。只要时间允许,我几乎可以测试我的应用程序的几乎每一个类/公共方法。