Android:如何进行单元测试" IllegalStateException:在onSaveInstanceState"之后无法执行此操作

时间:2018-06-19 04:32:03

标签: android unit-testing testing

我的应用程序崩溃,有时在活动生命周期后调用dialog.show。我知道这发生了什么,并希望对应用程序中发生的每个错误进行单元测试,以避免它再次出现。但是这样的事情怎么会(单位?)测试?

1 个答案:

答案 0 :(得分:3)

难以对异常进行单元测试,因为异常消息所暗示的发生与活动生命周期紧密相关-隔离发生实际上是不可能的。

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

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

  1. 您可以实例化一个内部队列,该内部队列存储延迟与FragmentTransaction相关的方法执行的功能,并在尝试执行onSaveInstanceState方法时识别活动是否已调用show()。 如果活动处于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并开发集成测试验证:

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

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