Robolectric buildActivity() с шпионами Mockito?
Мне кажется, что создание Activity unit test с утилитами жизненного цикла Robolectric (начиная с Robolectric.buildActivity()
) и шпионаже в отношении одной и той же операции с шпионами Mockito являются взаимоисключающими.
Поскольку buildActivity()
управляет конструкцией объекта Activity, единственным местом для добавления шпиона для Activity является вызов buildActivity()
. Однако шпион не работает должным образом, когда он добавляется после факта.
Это особенно верно при шпионаже за побочными эффектами методов жизненного цикла ActivityController
, таких как create()
, start()
и resume()
. Я предполагаю, что это происходит потому, что ActivityController содержит ссылку на "реальный" объект Activity, а не на шпион, который был добавлен позже.
Итак, есть ли способ отслеживать действие, которое тестируется с помощью Robolectric, так что шпион работает правильно при вызове методов жизненного цикла через Robolectric ActivityController
?
Ответы
Ответ 1
По крайней мере, для случая, когда действие не является объектом, находящимся под тестированием, а только фиктивная активность, которая содержит тестируемый фрагмент, можно ввести макет в тестовую активность, которая может проверять взаимодействие с активностью через коммуникационный интерфейс между фрагментом и активностью (после http://developer.android.com/training/basics/fragments/communicating.html).
Ответ 2
Ответ заключается в использовании отражения для замены "реального" объекта Activity
в ActivityController
.
@Test
public void someTestMethod() throws NoSuchFieldException, IllegalAccessException {
ActivityController<LoginActivity> ac = Robolectric.buildActivity(LoginActivity.class);
LoginActivity spiedActivity = spy(ac.get());
replaceComponentInActivityController(ac, spiedActivity);
ac.create();
// do your work
}
public static void replaceComponentInActivityController(ActivityController<?> activityController, Activity activity)
throws NoSuchFieldException, IllegalAccessException {
Field componentField = ComponentController.class.getDeclaredField("component");
componentField.setAccessible(true);
componentField.set(activityController, activity);
}
Я тестирую его на Robolectric
3.1, и это нормально.