Android: Модульное тестирование Android-приложений с Robolectric и Mockito

У меня есть библиотека Java, которая использует несколько вещей из Android API. Я хотел бы использовать Mockito для написания модульных тестов для этой библиотеки.

Есть ли способ, которым я могу это сделать?

Mockito плохо работает на виртуальной машине Dalvik, см. этот пост: Использование Mockito с виртуальной машиной Android< /а>

ОБНОВЛЕНИЕ:

После этого поста я открыл для себя Robolectric, и у меня была возможность поработать в Pivotal Labs и внести небольшой вклад в эту библиотеку. Я бы рекомендовал использовать это поверх платформы тестирования Android/mockito. Кроме того, вы можете использовать Robolectric И Mockito, но теневые объекты в Robolectric делают Mockito ненужным для большинства случаев использования.

Проблема с попыткой модульного тестирования Android заключается в том, что в библиотеке Android, на которой вы строите, каждый метод заглушен, чтобы либо генерировать исключение-заглушку, либо возвращать null. Если вы хотите протестировать свое приложение и хотите получить какое-либо поведение Android, вам не повезло, если только вы не используете Robolectric, который переписывает байт-код на лету при загрузке классов и внедряет теневой объект, который имитирует поведение.

ОБНОВЛЕНИЕ 2:

Прошло некоторое время, и все изменилось. Многие классы Shadow в Robolectric были заменены настоящими классами Android. Теперь используются настоящие jar-файлы Android, и Robolectric загружает классы Shadow только для гораздо меньшего набора вещей. Это еще одна причина использовать Robolectric для тестирования Android.


person Christopher Perry    schedule 10.11.2011    source источник


Ответы (4)


После долгих поисков в Google я нашел ответ на этот здесь.

В основном это связано с использованием среды модульного тестирования Robolectric, которая перехватывает загрузку классов Android. Затем вы можете использовать Mockito (хотя в большинстве случаев это не обязательно) и запускать тесты на JVM!

person Christopher Perry    schedule 17.11.2011
comment
Я использую Spy-конструкт от Mockito в сочетании с конструкторами от Robolectric. Таким образом, я могу частично издеваться над компонентами Android, когда это необходимо, например. FooActivity foo = spy(Robolectric.buildActivity(FooActivity.class).get()); doReturn(mock).when(foo).getSomething(); - person Alix; 01.09.2015

Начиная с версии 1.9.5 (выпущенной 3 июня 2012 г.) вы можете использовать Mockito с Android. Для этого вам также потребуется dexmaker:

http://code.google.com/p/dexmaker/

Эта вики-страница описывает, как это реализовать:

http://code.google.com/p/dexmaker/wiki/Mockito

person Ian Newson    schedule 19.06.2012
comment
Это не дает вам никакого поведения Android. Robolectric по-прежнему лучший выбор, поскольку он предоставляет Mocks (теневые классы) и поведение Android. - person Christopher Perry; 19.06.2012
comment
Я понимаю, но ваш вопрос был не в том, «какая лучшая платформа для насмешек для Android», а в том, «как я могу использовать Mockito с Android». - person Ian Newson; 19.06.2012
comment
@ChristopherPerry Я думаю, что на самом деле может быть некоторая путаница. Использование Mockito таким образом с инфраструктурой тестирования Android и JUnit означает, что ваши тесты выполняются на реальном устройстве или эмуляторе, что означает, что доступны все классы Android. Платформа тестирования Android также предоставляет встроенные макеты, такие как MockContext. - person Ian Newson; 20.06.2012
comment
Да, но среда тестирования Android ужасна. Я обновил вопрос, чтобы отразить общую тему. - person Christopher Perry; 20.06.2012
comment
@ChristopherPerry, вы обновили свой вопрос, хотя на самом деле ваше редактирование должно быть отдельным ответом (как это уже есть). Это похоже на плохой этикет. - person Ian Newson; 20.06.2012

Взгляните на android-mock. Он основан на EasyMock 2.4 (поэтому не так хорош, как Mockito, но близко).

Он обходит ограничения DalvikVM, предварительно создавая фиктивные классы во время сборки, а не во время выполнения, а затем связывая их с скомпилированным тестовым кодом при развертывании на устройстве.

Также существует мок-фреймворк под названием Borachio, за который я не могу поручиться, но он выглядит многообещающе. (если вы готовы выполнить действия по запуску Scala на вашем устройстве).

person tomtheguvnor    schedule 11.11.2011
comment
Да, я знаю об этом. Я стараюсь не использовать его, если в этом нет необходимости. Синтаксис Mockito намного приятнее. - person Christopher Perry; 11.11.2011

Вы можете избежать этого для всего, что не имеет ничего общего с внутренними классами Android SDK. Это то, что я делаю для своих проектов Android (хотя я использую JMock2, а не Mockito).

У меня есть два тестовых проекта.

  • Первый использует JUnit4 и JMock2, которые я добавил в качестве зависимостей. Я тестирую все классы «бизнес-логики», но не могу протестировать ничего, что связано с Android (классы пользовательского интерфейса, SQLiteOpenHelper и т. д.). Если я попытаюсь использовать их в своих тестах, я получу ужасное исключение Stub!.

  • Второй для тестирования пользовательского интерфейса с использованием ActivityInstrumentationTestCase2 и Robotium.

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

person Guillaume    schedule 12.11.2011
comment
Вздох. Проблема в том, что мои классы бизнес-моделей используют AsyncTask для захвата каждой части данных, которые я использую в приложении, на каждой странице. Я подумал, поскольку AsyncTask — это, по сути, POJO, я мог бы просто взять код для него, поместить его в свой проект и потерять зависимость. - person Christopher Perry; 13.11.2011
comment
На вашем месте я бы попытался абстрагировать все зависимости Android от интерфейсов, чтобы заглушка не мешала. Вероятно, с AsyncTask не так просто, как кажется... - person Guillaume; 13.11.2011
comment
@Chirstopher Perry: Вы нашли какое-то решение своей проблемы для эффективного тестирования задач ASync? Я сейчас в той же лодке. - person bianca; 17.03.2013