I am using Robotium to functionally test an Android app. I'd like to test the onResume behaviour after onDestroy has been called. This post hints on using Instrumentation, but i can't get it to work. I have included the following, but this fails with an IllegalStateException. Is it possible to destroy the app and restart it?
public class MainActivityFunctionalTest extends ActivityInstrumentationTestCase2<MainActivity> {
private Solo solo;
public MainActivityFunctionalTest() {
super(MainActivity.class);
}
public void testActionList() {
getInstrumentation().callActivityOnDestroy(solo.getCurrentActivity());
...
}
Results in the following exception:
java.lang.IllegalStateException: Must be called from main thread of process at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1373) at android.app.FragmentManagerImpl.dispatchDestroy(FragmentManager.java:1825) at android.app.Activity.performDestroy(Activity.java:5171) at android.app.Instrumentation.callActivityOnDestroy(Instrumentation.java:1109) at nl.handypages.trviewer.test.MainActivityFunctionalTest.testActionList(MainActivityFunctionalTest.java:81) at java.lang.reflect.Method.invokeNative(Native Method) at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:214) at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:199) at android.test.ActivityInstrumentationTestCase2.runTest(ActivityInstrumentationTestCase2.java:192) at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:190) at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:175) at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:555) at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1584)
You can simulate a configuration change like this:
getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
activity.recreate();
}
});
setActivity(null);
activity = getActivity();
This will result in a new instance of the activity being created, and it should go through the lifecycle correctly (including passing the bundle to restore from to the new activity). Note that this only works in Honeycomb (API level 11) and higher.
Well you have two issues here, the first issue is that the instrumentation callactivityondestroy methods require you to call it from the main thread. see runOnUiThread usage tips for details on how to do this.
The second issue is that (and i might be wrong here) is never suppose to go from onDestroy to onResume http://developer.android.com/reference/android/app/Activity.html says that after ondestroy the activity is literally destroyed. You would have to create a new instance of the activity to get another onResume. with you could do by launching your activity again. I suppose you could do it your way but im not sure how valid it would be, if you wanted to do it in such a way, just call the onResume in the same way as onDestroy as noted in the question i linked to.
I don't think you can resume an activity that is already destroyed. If your activity is not destroyed, but only stopped, then you can restart and resume it. OnResume needs to be called on a UI thread, so suppose you want to test the resume state after the activity is already running, you can do this:
@UiThreadTest
public void testResumeAfterStop() {
Instrumentation instr = this.getInstrumentation();
// here, test or record down whatever should be tested
// when the activity is in resume state the first time
instr.callActivityOnPause(getActivity());
instr.callActivityOnStop(getActivity());
instr.callActivityOnRestart(getActivity());
instr.callActivityOnStart(getActivity());
instr.callActivityOnResume(getActivity());
// Now you are in the resume state again.
// Test whatever you need here.
}
Thanks. I added and called this.
public void callActivityOnDestroy(final Activity activity){
getInstrumentation().runOnMainSync(new Runnable() {
public void run() {
activity.finish();
}
});
}
public void callActivityStart(final Activity activity){
getInstrumentation().runOnMainSync(new Runnable() {
public void run() {
activity.startActivity(new Intent(activity, MainActivity.class));
}
});
}
And alternatively (in my case) i can just call (if i don't want to complete kill the process):
getInstrumentation().callActivityOnStop(getActivity());
getInstrumentation().callActivityOnRestart(getActivity());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With