How do you force a configuration change in an Android Robolectric test?

蓝咒 提交于 2019-12-03 22:29:08

What Android API level are you compiling against? If it's 3.0 or above you could try Activity.recreate(). The documentation states:

Cause this Activity to be recreated with a new instance. This results in essentially the same flow as when the Activity is created due to a configuration change -- the current instance will go through its lifecycle to onDestroy() and a new instance then created after it.

Haven't tried it myself though.

Calling recreate in Robolectric (note that you don't have to worry about older API versions when using Robolectric) is pretty close to simulating a configuration change, but won't necessarily catch all errors you could make. In particular it does not create a new instance of the Activity (and I'm pretty sure it does not 'scrub' it), so if you have forgotten to restore member fields of your Activity your tests won't catch that. It does work well enough for testing fragments though (non retained fragments are destroyed and re-instantiated).

If you call recreate on an Activity in a Robolectric test the following happens:

  1. onSaveInstanceState
  2. onPause
  3. onStop
  4. onDestroy
  5. onCreate
  6. onStart
  7. onRestoreInstanceState
  8. onResume

(I found this out by overriding most lifecycle methods in a test activity and putting logging statements in them)

You can get a little closer to a real configuration change with code like the following:

Bundle bundle = new Bundle();
activityController.saveInstanceState(bundle).pause().stop().destroy();
controller = Robolectric.buildActivity(YourActivity.class).create(bundle).start().restoreInstanceState(bundle).resume();
activity = controller.get();

(This code is for Robolectric 2.1 - if you are on 2.2 or up, you will possibly want a .visible() call after that .resume())

Using the above you will see the following events occur:

  1. onSaveInstanceState
  2. onPause
  3. onStop
  4. onDestroy
  5. new instance of Activity instantiated (all following calls are on this new instance)
  6. onCreate
  7. onStart
  8. onRestoreInstanceState
  9. onResume
  10. onPostResume

This still isn't an exact match but is much closer to what will happen when a real configuration change is encountered.

I think this might be a decent simulation of what happens when an activity is destroyed due to low memory, as unlike calling recreate() I don't think this will keep hold of references to retained fragments. I'm on shaky ground in this area though!

Update:

If your Activity was started via an intent, you might need to add in a call to withIntent, like so:

Robolectric.buildActivity(YourActivity.class).withIntent(intent).create(bundle) // and so on...

I've had success using ZoFreX's answer, however I'd like to add how to actually simulate the rotation. I know the OP specified that rotation is not an absolute must, but the title hints that this should be included in the answer, and could help people who end up straying here.

basically, set the orientation of the activity before applying ZoFrex's solution. Or more concisely in code:

// toggle orientation
int currentOrientation = fragment.getActivity().getResources().getConfiguration().orientation;
boolean isPortraitOrUndefined = currentOrientation == Configuration.ORIENTATION_PORTRAIT || currentOrientation == Configuration.ORIENTATION_UNDEFINED;
int toOrientation = isPortraitOrUndefined ? Configuration.ORIENTATION_LANDSCAPE : Configuration.ORIENTATION_PORTRAIT;
Robolectric.application.getResources().getConfiguration().orientation = toOrientation;

// ZoFreX's solution
Bundle bundle = new Bundle();
activityController.saveInstanceState(bundle).pause().stop().destroy();
controller = Robolectric.buildActivity(YourActivity.class).create(bundle).start().restoreInstanceState(bundle).resume();
activity = controller.get();

Please checkout ZoFreX's solution because it contains additional info not included here.

The ActivityController class of Robolectric has a configurationChange() method that probably handles this. Hell, it even has a javadoc comment! :D

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!