#android
Вопрос:
Убираем все на всякий случай.
Комментарии:
1. Вы следили за этой настройкой тестирования рукояти? youtube.com/watch?v=nOp_CEP_EjM
2. Эта настройка предназначена для тестирования контрольно-измерительных приборов, мой модульный тест @muetzenflo
3. В таком случае ответ прост: это не сработает. У UnitTests нет AndroidContext. Они возможны только для чистого кода Kotlin (логика, отличная от Android). Как только вам понадобится что-то вроде
Context
илиApplication
(что является частью Hilt), вам нужно будет использовать инструментальные тесты. Отказ от ответственности: Я не профессионал в тестировании, и есть вероятность, что прямо сейчас я несу чушь. Но я совершенно уверен, что рукоять не может использоваться в чистых юниттестах.4. Спасибо вам за ваш ответ. Да, я так и подумал, вопрос в том, могу ли я запускать тесты инструментов, такие как модульные тесты? У меня также нет опыта в тестировании, но если бы я каким-то образом мог получить контекст приложения и перейти к hilt, это было бы потрясающе. Для этого потребуется настроить его так, как я еще не пробовал, но буду с нетерпением ждать, чтобы сделать это, если это возможно.
5. Хорошо, я проверю менее чем через 2 дня, если это сработает, я скажу вам, чтобы вы опубликовали правильный ответ. Спасибо!
Ответ №1:
Вы сталкиваетесь с двумя различными проблемами:
- Использование рукояти в едином тесте
- Нужно ввести текст приложения в UnitTest
объявление 1) Я на 90% уверен, что вы не можете использовать Hilt в UnitTests, но я с радостью обновлю этот ответ, если кто-нибудь предоставит другую информацию. Почему нельзя использовать Эфес в бронежилетах? По той же причине, что и номер 2 (см. Ниже), поскольку рукоять плотно связана с конструкцией андроида.
объявление 2) Это определенно невозможно, и на самом деле основное различие между UnitTests и инструментальными тестами на Android: последние выполняются в среде Android (реальное устройство, эмулятор и т. Д.). Из-за этого можно тестировать компоненты вашего кода, использующие классы Android. Наиболее знаменито ApplicationContext
, Context
, Activity
и Fragment
. ЮнитТесты, с другой стороны, являются необработанными логическими тестами и не связаны с какими-либо компонентами платформы Android. Для UnitTest не требуется класс Android. Ни один класс Android не доступен для UnitTests.
Таким образом, в вашем случае вы хотите использовать Hilt для теста, в который необходимо ввести текст приложения. Оба являются сильными индикаторами того, что вы должны сделать это в тесте инструментов. Вот пошаговая инструкция по настройке рукоятки для тестирования контрольно-измерительных приборов, как описано в этом видео:
https://www.youtube.com/watch?v=nOp_CEP_EjM
- добавьте следующие зависимости сортировки:
androidTestImplementation "com.google.dagger:hilt-android-testing:2.38.1"
kaptAndroidTest "com.google.dagger:hilt-android-comiler:2.38.1"
- Чтобы использовать эфес, вам нужно поменять
AndroidJUnitRunner
его на небольшой пользовательский раннер. Для этого создайте этоHiltTestRunner
:
import android.app.Application
import android.content.Context
import androidx.test.runner.AndroidJUnitRunner
import dagger.hilt.android.testing.HiltTestApplication
class HiltTestRunner : AndroidJUnitRunner() {
override fun newApplication(cl: ClassLoader?, className: String?, context: Context?): Application {
return super.newApplication(cl, HiltTestApplication::class.java.name, context)
}
}
- Чтобы рассказать gradle о новом тестовом бегуне, откройте свою
/app/build.gradle
и обменяйтесь этой строкой:
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
со ссылкой на класс HiltTestRunner
, который вы только что создали:
testInstrumentationRunner "your.package.HiltTestRunner"
В принципе, так оно и есть. Теперь вы можете создать новый модуль в своих тестовых папках точно так же, как вы сделали бы это в обычной папке приложения. Например:
@Module
@InstallIn(SingletonComponent::class)
class TestDatabaseModule {
@Provides
@Named("test_database")
fun provideDatabase(@ApplicationContext applicationContext: Context): MyDatabase {
return Room.inMemoryDatabaseBuilder(applicationContext, MyDatabase::class.java)
.allowMainThreadQueries()
.build()
}
}
Чтобы внедрить эту базу данных в свой тестовый код, вам необходимо создать HiltAndroidRule
и вызвать hiltRule.inject()
@Before
метод:
@HiltAndroidTest
class UserDaoTest {
@get:Rule
var hiltRule = HiltAndroidRule(this)
@get:Rule
val testCoroutineRule = TestCoroutineRule()
@Inject
lateinit var database: MyDatabase
private lateinit var sut: UserDao
@Before
fun createDb() {
hiltRule.inject()
sut = database.userDao()
}
@After
@Throws(IOException::class)
fun closeDb() {
database.clearAllTables()
database.close()
}
@Test
@Throws(Exception::class)
fun insertAndGetUserFromDb_success() = testCoroutineRule.runBlockingTest {
// Given a database with 1 user
val newUser = UserFakes.get()
sut.insert(newUser)
// When fetching the user
sut.get().test {
// Then the user fields should match
val user = awaitItem()
assert(user.id == newUser.id)
assert(user.name == newUser.name)
}
}
}
Дополнительная информация: Я использую турбину для упрощения потоков тестирования. Это часть кода выше, в которой я вызываю .test {}
Поток и awaitItem()
жду результата потока. Видишь турбину readme.md для получения дополнительной информации.