首页 > 解决方案 > Android:如何对“IllegalStateException:onSaveInstanceState 后无法执行此操作”进行单元测试

问题描述

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

标签: androidunit-testingtesting

解决方案


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

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

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

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

下面几行伪代码:

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

有activity返回resumed状态,执行所有挂起的函数

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

但是,这种方法不能免受配置更改的影响,一旦活动轮换,我们就会失去延迟调用。

  1. 或者,您可以使用ViewModel,它旨在在配置更改(例如旋转)中保留活动状态,并将第一种方法的延迟执行队列存储在视图模型中。确保存储延迟dialog.show()执行的函数不是匿名类 - 您最终可能会引入内存泄漏。

测试:

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

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

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

  4. 或者,我们仍然可以使用robolectric和开发集成测试验证:

    • 内部队列在被调用dialog.show()后推迟执行onSaveInstanceState
    • dialog.show()在活动调用onSaveInstanceState并再次返回状态后存储的内部队列执行挂起的执行resumed
    • dialog.show()活动处于//状态的情况下created立即执行startedresumed

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


推荐阅读