Подтвердить что ты не робот

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

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

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

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

Спасибо.

4b9b3361

Ответ 1

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

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

Не пробовал сам, хотя.

Ответ 2

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

Если вы вызываете воссоздание на Activity в Robolectric test, происходит следующее:

  • onSaveInstanceState
  • OnPause
  • OnStop
  • OnDestroy
  • OnCreate
  • OnStart
  • onRestoreInstanceState
  • 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())

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

  • onSaveInstanceState
  • OnPause
  • OnStop
  • OnDestroy
  • новый экземпляр действия, созданный экземпляром (все последующие вызовы находятся в этом новом экземпляре)
  • OnCreate
  • OnStart
  • onRestoreInstanceState
  • onResume
  • onPostResume

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

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

Update:

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

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

Ответ 3

У меня был успех с использованием ответа 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 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, потому что оно содержит дополнительную информацию, не включенную здесь.

Ответ 4

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