【发布时间】:2020-03-23 16:42:31
【问题描述】:
我有一个LiveData 变量,我想在收到来自HTTP request 的响应后为其赋值。我在launch {} 范围内分配了这个值。但是,当我测试代码以查看该值是否已实际分配时,测试失败并指出该值为null。
我尝试了另一种选择,即使用runBlocking {} 范围而不是launch {} 范围,并且我的测试用例通过了。用于联网的库是Retrofit
以下是使用launch() 并使测试用例失败的代码。
private var _state = MutableLiveData<State>()
val state: LiveData<State>
get() = _state
private var job = Job()
private val uiScope = CoroutineScope(job + Dispatchers.Main)
init {
executeRequest(....)
}
// Test cases fails with this function
private fun executeRequest(params) {
uiScope.launch {
val deferred = repository.getApi()
.requestAsync(params)
try {
val response = deferred.await()
_state.value = StateSuccess(response)
} catch (e: Exception) {
_state.value = StateError("Failure: $e.message")
}
}
}
以下是使用runBlocking() 并使测试用例通过的代码。
private var _state = MutableLiveData<State>()
val state: LiveData<State>
get() = _state
private var job = Job()
private val uiScope = CoroutineScope(job + Dispatchers.Main)
init {
executeRequest(....)
}
// Test cases passes with this function
private fun executeRequest(params) {
runBlocking {
val deferred = repository.getApi()
.requestAsync(params)
try {
val response = deferred.await()
_state.value = StateSuccess(response)
} catch (e: Exception) {
_state.value = StateError("Failure: $e.message")
}
}
}
这是测试用例
val viewModel = MyViewModel(fakeClientRepository)
val observer = Observer<State> {}
try {
viewModel.state.observeForever(observer)
assert(viewModel.state.value == StateSuccess("success"))
} finally {
viewModel.state.removeObserver(observer)
}
为什么launch() 没有将值赋给LiveData 变量?
【问题讨论】:
-
您必须检查
Observer中的值。在您的测试用例中,assert(viewModel.state.value == StateSuccess("success"))在observeForever()之后立即被调用,尽管您的 http 请求尚未完成。
标签: android kotlin coroutine kotlin-coroutines