Как вы заставляете изменение конфигурации в тесте Android Robolectric? - PullRequest
19 голосов
/ 19 мая 2011

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

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

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

Спасибо.

Ответы [ 4 ]

19 голосов
/ 17 февраля 2014

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

Если вы вызываете метод create в 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. новый экземплярдеятельности (всеэто новый экземпляр)
  6. onCreate
  7. onStart
  8. onRestoreInstanceState
  9. onResume
  10. onPostResume

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

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

Обновление:

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

Robolectric.buildActivity(YourActivity.class).withIntent(intent).create(bundle) // and so on...
10 голосов
/ 20 октября 2014

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

8 голосов
/ 20 июля 2011

На каком уровне API Android вы компилируете?Если это 3.0 или выше, вы можете попробовать Activity.recreate().Документация гласит:

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

Хотя сам не пробовал.

4 голосов
/ 08 января 2017

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

...