Современные практики мобильного программирования и практики программирования в целом уделяют большое внимание разработке через тестирование. Если вы хотите разработать приложение для Android с использованием Kotlin, лучше всего помнить о TDD, потому что это позволит разбить ваше приложение на отдельные тестируемые компоненты, что упростит разработку тестов и поиск ошибок в вашем приложении.

Если приложение будет иметь какие-либо функции CRUD, хорошим выбором будет Firebase. Firebase имеет встроенную интеграцию с Android Studio и ее очень легко настроить, если у вас нет опыта работы с серверной частью, что делает ее отличным выбором как для начинающих, так и для опытных программистов.

Имея в виду TDD, вы, вероятно, захотите протестировать свои методы, использующие Firebase, чтобы убедиться, что все работает правильно.

Строка Firebase по тестированию - это распространенное решение - использовать непроизводственную базу данных и выполнять фактические действия чтения и записи с этой базой данных, чтобы убедиться, что все работает (Документация Firebase).

С помощью этого метода вы просто можете использовать Firebase как обычно - только в другой базе данных, чтобы убедиться, что вы ничего не испортили в производственной среде.

Но что, если вы не хотите использовать непроизводственную базу данных? Либо вы разработчик-одиночка, который не хочет поддерживать две базы данных, либо у вас много времени нет доступа в Интернет?

В этом блоге я покажу вам, как с помощью Mockito имитировать различные функции Firebase и выполнять локальное модульное тестирование.

Установка

Я собираюсь показать, как имитировать Firebase на примере сценария. Допустим, у вас есть приложение CRUD с функцией входа. У вас есть класс-оболочка вокруг Firebase (лучшая практика на случай, если вы позже измените свой сервер) под названием LogInModel.

LogInModel имеет функцию LogIn(email, password), которую мы хотим протестировать. LogIn просто вызывает класс Firebase FirebaseAuth с помощью метода signInWithEmailAndPassword. Вот как будет выглядеть метод LogIn в LogInModel на базовом уровне:

В приведенном выше фрагменте вы можете заметить объект observer. observer относится к типу LogInListener, который я определю ниже.

LogInListener - это простой interface, который другие классы могут придерживаться, чтобы знать, был ли вход в систему неудачным или успешным. LogInListener просто определяется так:

Итак, мы пытаемся проверить с помощью нашего модульного теста, чтобы убедиться, что logIn выполняет то, что должен делать, - входит в систему с помощью Firebase. Теперь с помощью этого примера очевидно, что он делает то, что должен, поскольку код такой короткий, но в более крупных проектах тестирование становится необходимостью.

Тесты

Мы собираемся провести модульный тест (в Android Studio, который называется «тест») под названием LogInModelTest. Наш тестовый класс будет использовать Mockito для имитации объекта firebase, который мы используем для проверки функциональности нашего класса.

Я разобью LogInModelTest раздел за разделом, чтобы подробно описать, как построен класс.

Это начало нашего тестового файла.

В первой строке вы увидите наши тестовые инструментыLogInListener - это упрощает получение результата logIn метода, который мы тестируем. Поскольку у нас есть этот implements в конце файла, вы заметите, что у меня были методы из интерфейса LogInListener в.

Затем у нас есть @Mock private val mAuth: FirebaseAuth, объект Firebase, над которым мы издеваемся.

LogInModel - это объект, который мы собираемся проводить для модульного тестирования.

Два Task ', которые вы видите, переопределяют результат входа в Firebase. Это позволяет нам проверить неудачный и успешный вход в систему.

Три private const val предназначены для обновления результата вызовов LogInListener. Вы можете заменить это перечислением, что является наилучшей практикой, но чтобы прояснить, что я собираюсь сделать, я просто использовал их как отдельные переменные. Они используются с logInResult.

Это наш метод установки @Before.

MockitoAnnotations.initMocks(this) просто настраивает наши фиктивные объекты.

Здесь я определяю successTask и failureTask. Теперь Task - это интерфейс, поэтому я определяю так много функций ( содержит больше функций). Я выделяю здесь только самые важные.

В конце метода мы просто инициализируем остальные переменные.

Теперь о методах тестирования!

Здесь мы тестируем успешный вход.

Сначала мы настраиваем комбинацию электронной почты и пароля.

Затем мы используем Mockito.when, чтобы убедиться, что при вызове нашего объекта FirebaseAuth мы собираемся вернуть successTask (задача, сигнализирующая об успешном входе в систему) и не получить исключение нулевого указателя или другое неожиданное поведение.

Мы вызываем logIn в тестируемом классе, а затем утверждаем, что наша попытка входа в систему увенчалась успехом. logInResult устанавливается интерфейсом, о котором я упоминал ранее.

Если вместо этого вы хотите проверить ошибку, вы просто проверяете, что вызов привел к ошибке, и используйте failureTesk с вызовом Mockito.when. Вот пример этого:

Наконец, мы переходим к последнему оставшемуся коду в нашем классе - методам интерфейса!

Здесь мы просто устанавливаем logInResult = SUCCESS, если попытка входа была успешной, в противном случае мы устанавливаем FAILURE. Это позволяет утвержденному выше утверждению, которое вы видели, работать.

Вот и все! Хотя это определенно немного больше кода, чем использование отдельной непроизводственной базы данных, его определенно можно выполнить с помощью модульного тестирования Firebase без необходимости в указанной дополнительной базе данных. Если вы разделите код на более мелкие части, вы увидите, что ни один из них не является особенно сложным. Удачного тестирования!

Для справки вот весь класс в одном фрагменте:

И если вы зашли так далеко, вот в знак моей признательности!

Нажмите 👏, чтобы сказать «спасибо!» и помогите другим найти эту статью.

Чтобы быть в курсе отличных новостей о Kt. Academy, подписывайтесь на рассылку новостей, следите за Твиттером и следите за нами в среде.

Если вам нужна мастерская Kotlin, узнайте, чем мы можем вам помочь: kt.academy.