单元测试android

单元测试android,android,unit-testing,Android,Unit Testing,单元测试android应用程序通常比预期的要困难,因为有些类没有公共构造函数(如NotificationManager),有些类的方法无法重写,如Context.getText 对于NotificationManager,我使用了一个委托人。对于上下文,我也会这样做,但这意味着在所有使用上下文的类(很多)中,我需要使用自己的上下文,而这些上下文甚至不能从上下文派生。然后,每当我需要将上下文传递给Android API时,我都需要从包装器中获取真正的上下文 这是正确的吗?还有别的办法吗?宣布这些方

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

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

这是正确的吗?还有别的办法吗?宣布这些方法为最终方法的理由是什么? 有没有人真正为Android的大型应用程序编写过单元测试

编辑

我找到了将getText方法定义为final的原因:它是一个模板方法。因此,覆盖被调用的非final方法就足够了


我也发现这是可行的,但有点奇怪,Android在很多方面对测试都很不友好

你可能想看看RoboeElectric

我想你已经读过了:


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

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

有些类没有公共构造函数(如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上下文的资源/组件(即活动、NotificationManager或TextView)都是从实际运行的app.apk实例获取的。如果您在测试项目中创建/使用自己的MockContext,您可以从图中看到,InstrumentationTestRunner将模拟对象注入正在运行的应用程序中

使用instrumentation test的缺点是效率,它会进入完整的运行生命周期(启动emulator->安装并启动test.apk和app.apk以及fire InstrumentationTestRunner),即使您只需要从单个类测试单个方法(如您在注释中所述)。我同意奥利的观点,这是一个充满敌意的设计

这就是他们的网站:Robolectric是一个单元测试框架,它设计了Android SDK jar,因此你可以测试驱动你的Android应用程序的开发。测试在工作站上的JVM内运行,时间为秒


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

问题是,如果您没有在代码中包装上下文类,我看不到通过只处理testcase来解决问题的方法。最终的方法不能被存根。例如,在我的例子中,当我只是测试一个类的一个方法时,应用程序启动了。你是说要测试一个方法,我需要运行应用程序吗?我想单独测试这个方法,这样就不用真正调用Android sdk了。顺便说一下,android sdk中有一个MockContext,应该用来在测试期间模拟上下文。问题是,由于最后的方法,我没有使用它。在你的回答中,你说:它进入了完整的运行生命周期(启动emulator->安装并打开test.apk和app.apk,然后运行instrumentation test)。“开放”是什么意思?我所看到的是,如果我不使用真实的上下文,我可以在不运行应用程序的情况下运行单元测试。我只需要安装它。只有在调用Context.getText时,才会创建扩展“应用程序”的类(调用onCreate)。我现在正在安装Robolectric。如果您使用Android测试项目编写测试代码,并通过InstrumentationTestRunner运行Android测试项目,那么答案是肯定的。如果你想在没有真正调用Android SDK的情况下对该方法进行测试,那么强烈建议考虑使用ROBOLICTIC。顺便说一句,Robolectric是目前唯一可用的解决方案,它允许您在不运行实际应用程序的情况下测试基于Android上下文的资源/组件