Как вы принудительно изменяете конфигурацию в тесте Android Robolectric?

Я использую robolectric для того, чтобы сделать тесты для Android очень быстрыми, чтобы быть полезными. Я хочу проверить, что код, который я написал, работает, пока ориентация экрана меняется, чтобы имитировать общий случай использования в реальном мире.

В частности, то, что я тестирую, является асинхронным HTTP-вызовом на сервер с анализируемым xml после того, как результат получен. У меня есть единичный тест на все, что отлично работает, но не может понять, как имитировать поворот экрана. Любое изменение состояния, которое заставляет заново воссоздать себя, прекрасно, это необязательно должно быть поворот экрана.

Решение, использующее эмулятор, не является вариантом, так как я запускаю свои тесты несколько раз в минуту, и они должны выполняться менее 2 секунд. Я также хотел бы, чтобы это работало с roboguice, если это возможно.

Благодарю.

Solutions Collecting From Web of "Как вы принудительно изменяете конфигурацию в тесте Android Robolectric?"

Какой уровень API Android вы компилируете? Если это 3.0 или выше, вы можете попробовать Activity.recreate() . В документации указано:

Объясните, что этот объект будет создан с новым экземпляром. Это приводит, по существу, к тому же потоку, что и при создании Activity из-за изменения конфигурации – текущий экземпляр перейдет через свой жизненный цикл в onDestroy () и затем создаст новый экземпляр, созданный после него.

Я не пробовал это сам.

Вызов воссоздания в Robolectric (обратите внимание, что вам не нужно беспокоиться о старых версиях API при использовании Robolectric) довольно близко к моделированию изменения конфигурации, но не обязательно поймает все ошибки, которые вы могли бы сделать. В частности, он не создает новый экземпляр Activity (и я уверен, что он не «счищает» его), поэтому, если вы забыли восстановить поля членов своей деятельности, ваши тесты не поймут это. Он работает достаточно хорошо для тестирования фрагментов, хотя (не сохранившиеся фрагменты уничтожаются и повторно создаются).

Если вы вызываете воссоздание на мероприятии в тесте Robolectric, произойдет следующее:

  1. onSaveInstanceState
  2. OnPause
  3. OnStop
  4. OnDestroy
  5. OnCreate
  6. OnStart
  7. onRestoreInstanceState
  8. onResume

(Я нашел это, переопределив большинство методов жизненного цикла в тестовой активности и введя в них записи ведения журнала)

Вы можете приблизиться к реальному изменению конфигурации с помощью кода, например:

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

(Этот код предназначен для Robolectric 2.1 – если вы на 2.2 или выше, вам может понадобиться .visible() после этого .resume() )

Используя вышеизложенное, вы увидите следующие события:

  1. onSaveInstanceState
  2. OnPause
  3. OnStop
  4. OnDestroy
  5. Новый экземпляр Activity (все последующие вызовы относятся к этому новому экземпляру)
  6. OnCreate
  7. OnStart
  8. onRestoreInstanceState
  9. onResume
  10. onPostResume

Это все еще не точное совпадение, но гораздо ближе к тому, что произойдет, когда произойдет реальное изменение конфигурации.

Я думаю, что это может быть достойное моделирование того, что происходит, когда активность уничтожается из-за низкой памяти, так как в отличие от call rereate () я не думаю, что это сохранит ссылки на сохраненные фрагменты. Хотя я нахожусь на шаткой почве в этой области!

Обновить:

Если ваша активность была запущена с намерением, вам может потребоваться добавить вызов withIntent, например:

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

У меня был успех с помощью ответа ZoFreX, однако я хотел бы добавить, как реально имитировать поворот. Я знаю, что ОП указывает, что ротация не является абсолютной необходимостью, но заголовок намекает, что это должно быть включено в ответ, и может помочь людям, которые в конечном итоге заблудились здесь.

В основном, установите ориентацию активности перед применением решения ZoFrex. Или более кратко в коде:

 // 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(); 

Пожалуйста, проверьте решение ZoFreX, потому что оно содержит дополнительную информацию, не включенную здесь.

Класс ActivityController Robolectric имеет метод configurationChange (), который, вероятно, справляется с этим. Черт, у него даже есть комментарий javadoc! : D