android - Android Kotlin 测试:确保 firebase 实时数据库数据创建在仪器测试之前同步运行
问题描述
如何确保在androidTest
运行之前将数据添加到 Firebase 实时数据库。
我使用 Firebase 模拟器运行测试并使用 Koin 进行依赖注入。初始设置如下所示:
@MediumTest
@RunWith(AndroidJUnit4::class)
class GratitudeDetailFragmentTest: AutoCloseKoinTest() {
private lateinit var gratitudeRepository: GratitudeRepository
private lateinit var appContext: Application
private lateinit var firebaseAuth: FirebaseAuth
private lateinit var firebaseDatabase: FirebaseDatabase
private val email = "testuser@gmail.com"
private val password = "x7yer3232!ss"
@ExperimentalCoroutinesApi
@Before
fun init() {
stopKoin()//stop the original app koin
appContext = ApplicationProvider.getApplicationContext()
firebaseDatabase = FirebaseDatabase.getInstance()
firebaseDatabase.useEmulator("10.0.2.2", 9000)
firebaseAuth = FirebaseAuth.getInstance()
firebaseAuth.useEmulator("10.0.2.2", 9099)
val myModule = module(override = true) {
single { firebaseDatabase }
single { firebaseAuth }
single {
GratitudeRepository.getInstance()
}
}
// start Koin!
startKoin {
// declare used Android context
androidContext(appContext)
// declare modules
modules(listOf(myModule))
}
//clear the data to start fresh
runBlocking {
// Clear all (the problem is that this fails with perm denied)
// firebaseDatabase.reference.setValue(null)
// Now Koin is started get the ref to repo
gratitudeRepository = GratitudeRepository()
// ensure we have a user created
firebaseAuth.createUserWithEmailAndPassword(email, password)
// ensure 1 task
make_lists()
}
}
@After
fun stop() {
stopKoin()
}
private fun make_lists() {
firebaseAuth.signInWithEmailAndPassword(email, password).addOnCompleteListener {
Timber.d("current user id: ${firebaseAuth.currentUser!!.uid}")
gratitudeListKey = firebaseDatabase.reference.child("gratitude_items").push().key!!
Timber.d("gratitude key id: $gratitudeListKey")
val gratitudeList = FirebaseGratitudeList(
gratitudeListId = gratitudeListKey,
userId = firebaseAuth.currentUser!!.uid,
createdDate = System.currentTimeMillis(),
gratitudeItems = null)
firebaseDatabase.reference.child("gratitude_items")
.child(gratitudeListKey).setValue(gratitudeList).addOnCompleteListener {
Timber.d("Created list")
}
}
}
至于实际测试本身,我尝试了很多东西,例如
@ExperimentalCoroutinesApi
@Test
fun newGratitudeList_displaysZeroItems() = runBlockingTest {
//Thread.sleep(2000)
val bundle = bundleOf("gratitudeListIdKey" to gratitudeListKey)
launchFragmentInContainer<GratitudeDetailFragment>(
bundle,
R.style.Theme_Sossego
)
}
但这仅在线程睡眠未注释时才有效,并且似乎runBlocking
不能保证@Before
测试的部分终止。
只有另一方面,如果我将生成列表代码移动到测试主体并移动launchFragmentInContainer
到 firebase 回调,那么我会收到一个关于无法在主循环器上运行的错误(显然它通常在 UI 线程上,我猜是 Firebase 回调是强迫它成为主要的调度员?)
@ExperimentalCoroutinesApi
@Test
fun newGratitudeList_displaysZeroItems() = runBlockingTest {
firebaseAuth.signInWithEmailAndPassword(email, password).addOnCompleteListener {
Timber.d("current user id: ${firebaseAuth.currentUser!!.uid}")
gratitudeListKey = firebaseDatabase.reference.child("gratitude_items").push().key!!
Timber.d("gratitude key id: $gratitudeListKey")
val gratitudeList = FirebaseGratitudeList(
gratitudeListId = gratitudeListKey,
userId = firebaseAuth.currentUser!!.uid,
createdDate = System.currentTimeMillis(),
gratitudeItems = null)
firebaseDatabase.reference.child("gratitude_items")
.child(gratitudeListKey).setValue(gratitudeList).addOnCompleteListener {
// Still seems to try to run this on main and gives problems :(
runBlockingTest {
val bundle = bundleOf("gratitudeListIdKey" to gratitudeListKey)
launchFragmentInContainer<GratitudeDetailFragment>(
bundle,
R.style.Theme_Sossego
)
}
}
}
}
在我的 android 测试之前,我可以通过什么方式确保 firebase 数据 100% 完成,这样它们就不会不稳定?
解决方案
推荐阅读
- if-statement - 将代码块 PineScript 转换为 thinkscript
- python - 使用 cartopy 绘制地图时如何修改边距?
- python - 有一些 numpy.map 吗?
- python - 每当我使用“manage.py”时,我都会收到以下错误 AttributeError: 'list' object has no attribute 'read'
- node.js - 在 docker 容器中配置高 CPU
- hyperledger-fabric - 如何从超级账本作曲家中的一个链码调用另一个链码?
- php - 未定义索引:id NULL
- spring-boot - 用于 JPARepository 春季批处理 + 春季启动的 ItemReader
- git - 如何在 mix.exs 中使用带有语义版本控制的 Git 标签?
- node.js - 每次纱线后如何自动做一个工作流程?