android - 单元测试 LiveData android.os.Looper 未模拟
问题描述
我正在尝试对我的 ViewModel 进行单元测试,该 ViewModel 通过将一些内容发布回活动,LiveData
但是当我运行设置 livedata 值的方法时,我得到了错误
java.lang.RuntimeException:android.os.Looper 中的方法 getMainLooper 未模拟。
我已经阅读了几篇文章和文章,您所要做的就是添加一个Rule
forInstantTaskExecutorRule
并且它应该可以正常工作,但我这样做了,但我仍然得到错误。
这是我的单元测试
val observer: Observer<String> = mock(Observer::class.java) as Observer<String>
@get:Rule
var rule: TestRule = InstantTaskExecutorRule()
@Test
fun testSearchDataValidationFailureMissingSearchLocation() {
val viewModel = MoveViewModel()
val param1 = 0
val param2 = 1
val param3 = "1234"
viewModel.dialogMessageLiveData.observeForever(observer)
Assert.assertFalse(viewModel.validateSearchData(param1, param2, param3))
verify(observer).onChanged("Data not valid")
}
这是我正在尝试测试的方法
fun validateSearchData(param1: Int, param2: Int, param3: String): Boolean {
var valid: Boolean = false
if (param1 == 0 || param2 == 0 || param3.isBlank()) {
dialogMessageLiveData.postValue("Data not valid")
} else {
valid = true
}
return valid
}
我不确定还有什么办法可以解决这个问题,有人可以提出其他解决方案吗?
解决方案
您可以使用此扩展来获取 [LiveData] 的值或等待它具有一个超时。在主机端 (JVM) 测试中使用此扩展。建议与它一起使用InstantTaskExecutorRule
或类似的机制来同步执行任务。
@VisibleForTesting(otherwise = VisibleForTesting.NONE)
fun <T> LiveData<T>.getOrAwaitValue(
time: Long = 2,
timeUnit: TimeUnit = TimeUnit.SECONDS,
afterObserve: () -> Unit = {}
): T {
var data: T? = null
val latch = CountDownLatch(1)
val observer = object : Observer<T> {
override fun onChanged(o: T?) {
data = o
latch.countDown()
this@getOrAwaitValue.removeObserver(this)
}
}
this.observeForever(observer)
try {
afterObserve.invoke()
// Don't wait indefinitely if the LiveData is not set.
if (!latch.await(time, timeUnit)) {
throw TimeoutException("LiveData value was never set.")
}
} finally {
this.removeObserver(observer)
}
@Suppress("UNCHECKED_CAST")
return data as T
}
然后在您的测试用例中,您可以获得值
viewModel.dialogMessageLiveData.getOrAwaitValue()
推荐阅读
- json - 在 Flutter 中以间隔自动获取 API 数据
- angular - 在 if / else 中返回订阅结果
- reactjs - 如何使用带有 ReactJs 的 ChartistJs 库更改条形图标签的颜色和字体
- recursion - 在 mips 程序集中查找数组中元素的总和(使用递归)
- reactjs - redux-persist 在反应通用应用程序的服务器端渲染中不起作用
- java - Gradle 声明以抑制“未经检查”的警告不起作用
- docker - ENV、RUN 产生层、图像或容器?(了解文档问题)
- android - Google API:授权无效,不是有效的电子邮件或用户 ID
- jquery - 查找具有特定类的第一个 div;从底部开始
- vue.js - vuejs 中不存在名为“ROUTENAME”的 vue-router 路由