Reputation: 17339
I'm having a crash in my app where sometimes a dialog.show
is called after the activity's lifetime. I know where this happens and would like to unit test every bug that occurred in the app to avoid it to appear again. But how can something like this be (unit?) tested?
Upvotes: 3
Views: 499
Reputation: 2452
It's difficult to unit test the exception because the occurrence is tightly bound to the Activity lifecycle as the exception message suggests - the isolation of the occurrence is practically impossible .
You could employ Robolectric and try to verify whether the dialog.show()
method is invoked before onSaveInstanceState
call but I would not approach the problem this way. And the tests using Robolectric are no longer unit tests.
I met with a few solutions that eliminated the exception occurrence:
FragmentTransaction
-related methods execution and recognize whether the activity has called onSaveInstanceState
at the time the show()
method is attempted to be executed.
If the activity is in the created
/started
/resumed
state you could execute show()
immediately. If not, store the function deferring the show()
execution and execute them A few lines of pseudocode below:
if (isCreatedOrStartedOrResumed) {
dialog.show()
} else {
internalQueue.add {
dialog.show()
}
}
Has the activity returned to the resumed
state, execute all pending functions
fun onResume() {
super.onResume()
while(internalQueue.isNotEmpty()) {
internalQueue.poll().invoke()
}
}
This approach is not immune to configuration change though, we lose the deferred invocations once the activity gets rotated.
dialog.show()
executions are not anonymous classes - you may end up with memory leak introduced.Testing:
The way I would test the dialog displaying gracefully would be the Espresso
instrumentation tests.
I would also unit test view model storing/executing deferred executions. If we consider structuring code using MVP or MVVM architectural pattern we could store the deferred executions queue within one of the architecture class members and unit test them too.
I would also include LeakCanary as a safety net against memory leaks.
Optionally, we could still use robolectric
and develop integration test verifying:
dialog.show()
executions after onSaveInstanceState
gets calleddialog.show()
executions stored after activity has called onSaveInstanceState
and returned to the resumed
state again.dialog.show()
executed immediately in case the activity is in created
/started
/resumed
state.That's all I have at the moment, hope you will figure out the satisfactory tests suite verifying correct dialog displaying based on the approaches suggested.
Upvotes: 3