Android:如何对 "IllegalStateException: Can not perform this action after onSaveInstanceState"进行单元测试

标签 android unit-testing testing

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

最佳答案

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

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

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

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

下面几行伪代码:

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

Activity是否返回到resumed状态,执行所有挂起的函数

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

虽然这种方法不能避免配置更改,但一旦 Activity 旋转,我们就会丢失延迟调用。

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

测试:

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

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

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

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

    • onSaveInstanceState 被调用后,内部队列延迟 dialog.show() 执行
    • 在 Activity 调用 onSaveInstanceState 并再次返回到 resumed 状态后,内部队列执行未决的 dialog.show() 执行。
    • dialog.show() 立即执行,以防 Activity 处于created/started/resumed状态。

目前我只有这些,希望您能根据建议的方法找出令人满意的测试套件来验证正确的对话框显示。

关于Android:如何对 "IllegalStateException: Can not perform this action after onSaveInstanceState"进行单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50920689/

相关文章:

android - Android Activity中静态final的使用

java - 通过互联网在聊天应用程序中将音乐从手机传输到手机

单击运行时 Android Studio 不重建

loops - Jmeter 如何延迟永远发送请求?

java - 使用 MySQL 连接器连接数据库

scala - 使用 PrivateMethodTester 测试柯里化(Currying)方法

c++ - C++ Catch 是否有类似 NUnit 的 TestCase 的功能,具有多个参数/输入选项

ruby-on-rails - 如何对命名空间模型进行单元测试

java - 如何启用 Mockito 调试消息?

java - 模拟 IMAP 或 POP 服务器以进行单元测试的最简单方法是什么?