【问题标题】:Android: How to unit test "IllegalStateException: Can not perform this action after onSaveInstanceState"Android:如何对“IllegalStateException:onSaveInstanceState 后无法执行此操作”进行单元测试
【发布时间】:2018-06-19 04:32:03
【问题描述】:

我的应用程序发生崩溃,有时会在活动生命周期后调用 dialog.show。我知道这发生在哪里,并且想对应用程序中发生的每个错误进行单元测试,以避免它再次出现。但是如何才能对这样的东西进行(单元?)测试呢?

【问题讨论】:

  • 您的意思是如何使用单元测试来测试这些东西?

标签: android unit-testing testing


【解决方案1】:

很难对异常进行单元测试,因为正如异常消息所暗示的那样,事件与 Activity 生命周期紧密相关 - 事件的隔离实际上是不可能的。

您可以使用Robolectric 并尝试验证在onSaveInstanceState 调用之前是否调用了dialog.show() 方法,但我不会以这种方式解决问题。并且使用 Robolectric 的测试不再是单元测试。

我遇到了一些消除异常发生的解决方案:

  1. 您可以实例化一个内部队列存储函数,该函数延迟与FragmentTransaction 相关的方法执行,并在尝试执行show() 方法时识别活动是否调用了onSaveInstanceState。 如果活动处于created/started/resumed 状态,您可以立即执行show()。如果没有,则存储延迟 show() 执行的函数并执行它们

下面几行伪代码:

   if (isCreatedOrStartedOrResumed) {
      dialog.show()
   } else {
      internalQueue.add {
         dialog.show()
      }
   }

活动是否返回resumed状态,执行所有待处理函数

fun onResume() {
   super.onResume()
   while(internalQueue.isNotEmpty()) {
      internalQueue.poll().invoke()
   }
}

虽然这种方法无法避免配置更改,但一旦活动轮换,我们就会失去延迟调用。

  1. 或者,您可以使用ViewModel which is designed to retain the activity state across configuration change such as the rotation 并将第一种方法的延迟执行队列存储在视图模型中。确保存储延迟 dialog.show() 执行的函数不是匿名类 - 您最终可能会引入内存泄漏。

测试:

  1. 我测试优雅显示对话框的方法是Espresso 仪器测试。

  2. 我还将对存储/执行延迟执行的视图模型进行单元测试。 如果我们考虑使用 MVP 或MVVM architectural pattern 构建代码,我们可以将延迟执行队列存储在架构类成员之一中,并对它们进行单元测试。

  3. 我还会将LeakCanary 作为防止内存泄漏的安全网。

  4. 可选地,我们仍然可以使用robolectric 并开发集成测试验证:

    • 内部队列在 onSaveInstanceState 被调用后推迟 dialog.show() 执行
    • 在活动调用onSaveInstanceState 并再次返回resumed 状态后存储的内部队列正在执行待处理的dialog.show() 执行。
    • 如果活动处于created/started/resumed 状态,则立即执行dialog.show()

这就是我目前所拥有的一切,希望您能找到令人满意的测试套件,根据建议的方法验证正确的对话框显示。

【讨论】:

    猜你喜欢
    • 2011-11-20
    • 1970-01-01
    • 2016-02-08
    • 1970-01-01
    • 2015-08-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多