当我尝试使用corountines在kotlin中测试ViewModel时,出现Method myLooper in android.os.Looper not mocked
错误。
有ViewModel
class MainViewModel(private val uiContext: CoroutineContext = Dispatchers.Main) : ViewModel(), CoroutineScope {
private val heroesRepository: HeroesRepository = heroesRepositoryModel.instance()
val data = MutableLiveData<List<Heroes.Hero>>()
private var job: Job = Job()
override val coroutineContext: CoroutineContext
get() = uiContext + job
fun getHeroesFromRepository(page: Int) {
launch {
try {
val response = withContext(Dispatchers.IO) {
heroesRepository.getHeroes(page).await()
}
data.value = response.data.results
} catch (e: HttpException) {
data.value = null
} catch (e: Throwable) {
data.value = null
}
}
}
override fun onCleared() {
super.onCleared()
job.cancel()
}
}
以及我为此ViewModel做的测试
class HeroesDataSourceTest {
@Mock
lateinit var heroesRepository: HeroesRepository
@Mock
lateinit var deferred: Deferred<Heroes.DataResult>
val hero = Heroes.Hero(1, "superman", "holasuperman", 1, null, null)
val results = Arrays.asList(hero)
val data = Heroes.Data(results)
val dataResult = Heroes.DataResult(data)
@Before
fun initTest() {
MockitoAnnotations.initMocks(this)
}
@Test
fun testLoadInitialSuccess(): Unit = runBlocking {
`when`(heroesRepository.getHeroes(0)).thenReturn(deferred)
`when`(deferred.await()).thenReturn(dataResult)
var liveData: MutableLiveData<List<Heroes.Hero>>
val mainViewModel = MainViewModel(Dispatchers.Unconfined)
liveData = mainViewModel.data
mainViewModel.getHeroesFromRepository(0)
delay(10000L)
Assert.assertEquals(dataResult, liveData.value)
}
}
我调试了它,它给了我ViewModel的data.value = response.data.results
行中的错误。这是一个例外,但是可以肯定的是,由于数据为空,所以assertEquals将为false。
我检查了此线程:Method myLooper in android.os.Looper not mocked with Coroutines
还有此解决方案:https://android.jlelse.eu/mastering-coroutines-android-unit-tests-8bc0d082bf15
那行得通,但是在kotlin 1.3 kotlinx.coroutines.experimental.android.UI
中行不通。
答案 0 :(得分:2)
LiveData在内部使用MainLooper。添加此依赖项(或其支持库版本):
testImplementation "androidx.arch.core:core-testing:$lifecycle_version"
此规则:
@get:Rule
val instantExecutorRule = InstantTaskExecutorRule()
https://developer.android.com/reference/android/arch/core/executor/testing/InstantTaskExecutorRule