#android #kotlin #kodein
#Android #kotlin #kodein
Вопрос:
Я хотел бы внедрить поддельные переопределения в мои тесты инструментария Android с помощью Kodein. Я не знаю, какой подход является оптимальным для этого. Вот что я имею в виду:
- Мое приложение использует
KodeinAware
класс приложения. Обслуживаемый экземпляр Kodein содержит все зависимости, требуемые моим приложением. - В своих тестах я хотел бы внедрить переопределенные переопределения для определенных зависимостей, чтобы проверить поведение приложения в различных ситуациях.
- Переопределения должны быть разными для каждого теста и должны вводиться до / во время выполнения теста.
Является ли настраиваемое расширение Kodein разумным в этой ситуации или существует более простой и более подходящий подход (и если да, то какой)?
Ответ №1:
Если вашему тесту предоставлен Kodein
экземпляр (это означает, что он может использовать Kodein
объект, отличный от вашего Application
), то рекомендуемый подход заключается в создании нового объекта Kodein, который расширяет объект приложения и переопределяет все необходимые привязки.
val testKodein = Kodein {
extend(appKodein())
bind<MyManager>(overrides = true) with singleton { mock<MyManager>() }
}
Настраиваемый параметр Kodein рекомендуется использовать только в том случае, если вы используете статический «один истинный кодейн». Его использование исключает возможность параллельного запуска ваших тестов (поскольку все они обращаются к одному и тому же экземпляру Kodein) и заставляет вас переходить clear
ConfigurableKodein
между каждым тестированием и повторно объявлять каждый раз разные переопределения.
Комментарии:
1. Я использую этот подход в своих модульных тестах, то есть в тестах, которые проверяют правильное поведение введенных классов. Однако в моем инструментарии, точнее, в моих функциональных тестах, я тестирую экземпляр моего реального приложения. Чтобы сделать тесты детерминированными, я заменяю определенные зависимости в своем графике на mocks . Кодеин предоставляется
Application
экземпляром, следовательно, он похож на «единственный истинный кодеин». Прямо сейчас я тестирую настраиваемый подход kodein и вернусь, как только у меня будут некоторые результаты.
Ответ №2:
Теперь я использую ConfigurableKodein
внутренний пользовательский App
класс.
class App : Application(), KodeinAware {
override val kodein = ConfigurableKodein()
override fun onCreate() {
super.onCreate()
// A function is used to create a Kodein module with all app deps.
kodein.addImport(appDependencies(this))
}
}
// Helper for accessing the App from any context.
fun Context.asApp() = this.applicationContext as App
Внутри моего AppTestRunner
класса я объявляю конфигурацию изменяемой. Таким образом, я могу сбросить его конфигурацию между каждым тестом.
class AppTestRunner : AndroidJUnitRunner() {
override fun callApplicationOnCreate(app: Application) {
app.asApp().kodein.mutable = true
super.callApplicationOnCreate(app)
}
}
Я создал правило JUnit, которое сбрасывает график зависимостей перед каждым тестом.
class ResetKodeinRule : ExternalResource() {
override fun before() {
val app = InstrumentationRegistry.getInstrumentation().targetContext.asApp()
app.kodein.clear()
app.kodein.addImport(appDependencies(app))
}
}
Теперь в моих тестах я могу извлечь App.kodein
экземпляр и внедрить макеты, которые переопределяют зависимости исходного графика. Единственное, что нужно гарантировать, это то, что тестируемая активность запускается после настройки mocks, или поведение не предсказуемо.