我的应用程序发生崩溃,有时 dialog.show
在 Activity 的生命周期后被调用。我知道这种情况发生在哪里,并且想对应用程序中出现的每个错误进行单元测试,以避免它再次出现。但是,如何对这样的东西进行(单元?)测试?
最佳答案
很难对异常进行单元测试,因为正如异常消息所暗示的那样,事件与 Activity 生命周期紧密相关 - 事件的隔离实际上是不可能的。
您可以雇用 Robolectric并尝试验证是否在 onSaveInstanceState
调用之前调用了 dialog.show()
方法,但我不会以这种方式解决问题。并且使用 Robolectric 的测试不再是单元测试。
我遇到了一些消除异常发生的解决方案:
- 您可以实例化一个内部队列存储函数来延迟
FragmentTransaction
相关方法的执行,并识别 Activity 是否在show() 时调用了
方法试图被执行。 如果 Activity 处于onSaveInstanceState
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 旋转,我们就会丢失延迟调用。
- 或者,您可以使用 ViewModel which is designed to retain the activity state across configuration change such as the rotation并将第一种方法中的延迟执行队列存储在 View 模型中。确保存储延迟
dialog.show()
执行的函数不是匿名类 - 您最终可能会引入内存泄漏。
测试:
我测试对话框正常显示的方法是
Espresso
仪器测试。我还会对存储/执行延迟执行的 View 模型进行单元测试。 如果我们考虑使用 MVP 或 MVVM architectural pattern 构建代码我们可以将延迟执行队列存储在其中一个架构类成员中,并对它们进行单元测试。
我还会包括 LeakCanary作为防止内存泄漏的安全网。
可选地,我们仍然可以使用
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/