EnrollmentViewModelTest
@Test
fun getUserProfile() {
val responsesnapshot = this.javaClass.getResource("/userDetailResponse.json").readText()
val user = Gson().fromJson<User>(responsesnapshot,User::class.java)
val response = Response.success(user)
val deferred = CompletableDeferred<Response<User>>(response)
coEvery { userService.getUserDetail() } returns deferred
viewModel.getUserProfile()
assert(viewModel.loadingStatus.value != null)
assert(!UITestUtil.getvalue(viewModel.loadingStatus)!!)
assertEquals(false,viewModel.loadingStatus.value!!)
}
这是EnrollmentViewModel.kt
fun getUserProfile() {
loadingStatus.postvalue(true)
job = launch {
callAsync {
userService.getUserDetail()
}.onSuccess { user ->
if (user != null) {
processUserDetails(user)
}
loadingStatus.postvalue(false)
}.onError {
//
}.onException {
//
}
}
}
当我调试测试用例时,它表明UITestUtil.getvalue(viewModel.loadingStatus)!!是错误的。
但是很奇怪,测试用例没有通过,当我打印UITestUtil.getvalue(viewModel.loadingStatus)!!时。是真的。
它可能与loadingStatus.postvalue(true)
删除后,打印结果为假。
但是我不知道为什么。
object UITestUtil {
/**
* Gets the value of a LiveData safely.
*/
@Throws(InterruptedException::class)
fun <T> getvalue(liveData: LiveData<T>): T? {
var data: T? = null
val latch = CountDownLatch(1)
val observer = object : Observer<T> {
override fun onChanged(o: T?) {
data = o
latch.countDown()
liveData.removeObserver(this)
}
}
liveData.observeForever(observer)
latch.await(2,TimeUnit.SECONDS)
return data
}
}
已更新:
import com.google.gson.Gson
import kotlinx.coroutines.Deferred
import retrofit2.Response
import retrofit2.Response.success
data class VPlusResult<T : Any?>(
val response: Response<T>? = null,val exception: Exception? = null
)
inline fun <T : Any> VPlusResult<T>.onSuccess(action: (T?) -> Unit): VPlusResult<T> {
if (response?.isSuccessful == true)
action(response.body())
return this
}
inline fun <T : Any> VPlusResult<T>.onRawSuccess(action: (response: Response<T>) -> Unit): VPlusResult<T> {
if (response?.isSuccessful == true)
action(response)
return this
}
inline fun <T : Any,TR : Any> VPlusResult<T>.map(action: (T?) -> (TR)) =
if (response?.isSuccessful == true) VPlusResult(success(action(response.body())))
else this as VPlusResult<TR>
inline fun <T : Any> VPlusResult<T>.onError(action: (String) -> Unit): VPlusResult<T> {
if (response?.isSuccessful != true) {
response?.errorBody()?.let {
action(it.string())
}
}
return this
}
inline fun <T : Any,reified G : Any> VPlusResult<T>.onErrorJson(action: (G) -> Unit): VPlusResult<T> {
if (response?.isSuccessful != true) {
response?.errorBody()?.let {
action(Gson().fromJson(it.string(),G::class.java))
}
}
return this
}
inline fun <T : Any> VPlusResult<T>.onRawError(action: (Response<T>?) -> Unit): VPlusResult<T> {
if (response?.isSuccessful != true) {
action(response)
}
return this
}
inline fun <T : Any?> VPlusResult<T>.onException(action: (Exception) -> Unit) {
exception?.let { action(it) }
}
inline fun <T : Any> VPlusResult<T>.onSadness(action: (String?) -> Unit): VPlusResult<T> {
onError {
action(it)
}.onException {
action(it.message)
}
return this
}
suspend fun <T : Any> callAsync(block: () -> Deferred<Response<T>>): VPlusResult<T> {
return try {
VPlusResult(block().await())
} catch (e: Exception) {
VPlusResult(exception = e)
}
}
更新2:
在assert语句之前添加以下任一语句将获得false值,该值将通过测试用例。
coVerify { userService.getUserDetail() }
coVerify { viewModel.processUserDetails(user) }
更新3: 有趣的loadAllTasksFromRepository_loadingTogglesAndDataLoaded() 在https://github.com/android/architecture-samples中 也可以,但是我尝试将代码引入我的代码,但是也失败了。
@ExperimentalCoroutinesApi
@Test
fun getUserProfile4Using() {
// using TestCoroutinescope in kotlinx.coroutines.test
// Pause dispatcher so we can verify initial values
mainCoroutineRule.pauseDispatcher()
val responsesnapshot = this.javaClass.getResource("/userDetailResponse.json").readText()
val user = Gson().fromJson<User>(responsesnapshot,User::class.java)
val response = Response.success(user)
val deferred = CompletableDeferred<Response<User>>(response)
// coEvery { userService.getUserDetail() } returns deferred
viewModel.getUserProfile()
assert(viewModel.loadingStatus.value != null)
// verify { viewModel.processUserDetails(user) }
print(viewModel.loadingStatus.value)
assert(UITestUtil.getvalue(viewModel.loadingStatus)!!)
assertEquals(true,viewModel.loadingStatus.value!!)
// Execute pending coroutines actions
mainCoroutineRule.resumeDispatcher()
print(viewModel.loadingStatus.value!!)
assert(!UITestUtil.getvalue(viewModel.loadingStatus)!!)
assertEquals(false,viewModel.loadingStatus.value!!)
}