当测试一个函数时,我遇到了IndexOutOfBoundsException
的问题。通常情况下,usersInRangeViewStates
的大小应该是2,第一个条目是Resource.Loading
,第二个条目是Resource.Success
。因为usersInRange(...)
是一个异步函数,我必须等待它,所以我添加了runTest{ ... }
和advanceUntilIdle()
。实际上,我认为Asserts
的测试会一直等到异步函数完成,但这只是偶尔发生。有没有人看到这个错误,或者你能给我一个更好的解决方案?
代码:
val usersInRange: MutableLiveData<Resource<GETUsers>> = MutableLiveData()
fun getUsersInRange(myUserGeoPoint: GeoPoint, searchRadiusInMeter: Int) = viewModelScope.launch {
usersInRange.postValue(Resource.Loading())
val response = usersInRange(myUserGeoPoint, searchRadiusInMeter)
usersInRange.postValue(Resource.Success(response))
}
private suspend fun usersInRange(myUserGeoPoint: GeoPoint, searchRadiusInMeter: Int)
= withContext(Dispatchers.IO) {
val usersInRangeBuffer = GETUsers()
if(users.value is Resource.Success) {
for(user in (users.value as Resource.Success<GETUsers>).data.users) {
if(user.value.id == myUserID) continue
if(user.value.isInRange(myUserGeoPoint, searchRadiusInMeter)) {
usersInRangeBuffer.users[user.key] = user.value
}
}
}
usersInRangeBuffer
}
测试:
private lateinit var usersInRangeViewStates: MutableList<Resource<GETUsers>>
@Before
fun setUp() {
usersInRangeViewStates = mutableListOf()
viewModel.usersInRange.observeForever {
usersInRangeViewStates.add(it)
}
}
@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun `getUsersInRange() called should return 0 Users from 2 tested Users (plus myUser)`() = runTest {
val myUserGeoPoint = GeoPoint(1.0, 1.0)
val searchRadiusInMeter = 1000
val user01ID = "exampleUser01ID"
val user02ID = "exampleUser02ID"
val user01Location = GETLocation(0.0, 0.0)
val user02Location = GETLocation(0.0, 0.0)
val myUser = GETUser()
val user01 = GETUser(location = user01Location)
val user02 = GETUser(location = user02Location)
val mapUsers = mutableMapOf(myUserID to myUser, user01ID to user01, user02ID to user02)
val users = GETUsers(mapUsers)
val getUsers = Resource.Success(users)
viewModel.users.value = getUsers
viewModel.getUsersInRange(myUserGeoPoint, searchRadiusInMeter)
advanceUntilIdle()
Assert.assertTrue(usersInRangeViewStates[0] is Resource.Loading)
Assert.assertEquals(0, (usersInRangeViewStates[1] as Resource.Success).data.users.size)
Assert.assertFalse((usersInRangeViewStates[1] as Resource.Success).data.users.containsKey(user01ID))
Assert.assertFalse((usersInRangeViewStates[1] as Resource.Success).data.users.containsKey(user02ID))
Assert.assertFalse((usersInRangeViewStates[1] as Resource.Success).data.users.containsKey(myUserID))
}
1条答案
按热度按时间7y4bm7vi1#
viewModel.getUsersInRange
将Resource.Success(response)
发送到MutableLiveData
,然后MutableLiveData
请求主线程运行usersInRangeViewStates.add(it)
。advanceUntilIdle
将等待调度“运行观察者”任务。但是因为观察是在协程之外完成的,它可能不会等待任务实际完成运行。我认为你可以把测试作为另一件事在主线程上运行。