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