android - Android:如何对“IllegalStateException:onSaveInstanceState 后无法执行此操作”进行单元测试
问题描述
我的应用程序崩溃了,有时dialog.show
在活动的生命周期后调用 a 。我知道这发生在哪里,并且想对应用程序中发生的每个错误进行单元测试,以避免它再次出现。但是这样的东西怎么能被(单元?)测试?
解决方案
很难对异常进行单元测试,因为正如异常消息所暗示的那样,事件与 Activity 生命周期紧密相关 - 事件的隔离实际上是不可能的。
您可以使用Robolectric并尝试在dialog.show()
调用之前验证该方法是否被调用,onSaveInstanceState
但我不会以这种方式解决问题。并且使用 Robolectric 的测试不再是单元测试。
我遇到了一些消除异常发生的解决方案:
- 您可以实例化一个内部队列来存储延迟相关方法执行的函数,并在尝试执行该方法时
FragmentTransaction
识别该活动是否已调用。如果活动处于//状态,您可以立即执行。如果不是,则存储延迟执行的函数并执行它们onSaveInstanceState
show()
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()
}
}
但是,这种方法不能免受配置更改的影响,一旦活动轮换,我们就会失去延迟调用。
- 或者,您可以使用ViewModel,它旨在在配置更改(例如旋转)中保留活动状态,并将第一种方法的延迟执行队列存储在视图模型中。确保存储延迟
dialog.show()
执行的函数不是匿名类 - 您最终可能会引入内存泄漏。
测试:
我测试优雅显示的对话框的方法是
Espresso
仪器测试。我还将对存储/执行延迟执行的视图模型进行单元测试。如果我们考虑使用 MVP 或MVVM 架构模式来构建代码,我们可以将延迟执行队列存储在架构类成员之一中,并对它们进行单元测试。
我还将LeakCanary作为防止内存泄漏的安全网。
或者,我们仍然可以使用
robolectric
和开发集成测试验证:- 内部队列在被调用
dialog.show()
后推迟执行onSaveInstanceState
dialog.show()
在活动调用onSaveInstanceState
并再次返回状态后存储的内部队列执行挂起的执行resumed
。- 在
dialog.show()
活动处于//状态的情况下created
立即执行started
。resumed
- 内部队列在被调用
这就是我目前所拥有的一切,希望你能找到令人满意的测试套件,根据建议的方法验证正确的对话框显示。
推荐阅读
- python - Pandas 读取并解析显示为日期时间但不应该是日期时间的 Excel 数据
- node.js - 是否可以通过 nodejs 检查系统是否在 LAN 和 WiFi 上?
- javascript - 旋转自定义形状将其移动到角落
- ios - Swift 4 - iPhone 上的限制问题
- postgresql - 如何在 PostgreSQL 中按状态 DENSE_RANK()?
- python - 如何对包含多个文件的文件夹进行多线程处理?
- elasticsearch - 具有多个 must_not 条件的 Elasticsearch 行为不一致
- c++ - 我可以阻止用户在后台运行我的 C++ 程序吗?
- python - TypeError:“NoneType”对象不可迭代(h5 文件)
- kubernetes - _condition_ 在公制中是什么意思?