我已经看过this,并确保我的测试没有共享相同的模拟实例,但是当一起运行时测试仍然会失败,而单独运行时测试会成功。
我怀疑可能是有些原因导致每次测试后都无法重新模拟我的实例,但是我对Mockito的经验不足以找出问题所在
这是我的考试班
package com.relic.viewmodel
import android.arch.core.executor.testing.InstantTaskExecutorRule
import android.arch.lifecycle.Observer
import com.nhaarman.mockitokotlin2.*
import com.relic.api.response.Data
import com.relic.api.response.Listing
import com.relic.data.PostRepository
import com.relic.data.UserRepository
import com.relic.data.gateway.PostGateway
import com.relic.domain.models.ListingItem
import com.relic.domain.models.UserModel
import com.relic.presentation.displayuser.DisplayUserVM
import com.relic.presentation.displayuser.ErrorData
import com.relic.presentation.displayuser.UserTab
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.newSingleThreadContext
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.test.setMain
import org.junit.Before
import org.junit.Rule
import org.junit.Test
@ExperimentalCoroutinesApi
class UserVMTest {
@get:Rule
val rule = InstantTaskExecutorRule()
private lateinit var postRepo : PostRepository
private lateinit var userRepo : UserRepository
private lateinit var postGateway : PostGateway
private val username = "testUsername"
init {
val mainThreadSurrogate = newSingleThreadContext("Test thread")
Dispatchers.setMain(mainThreadSurrogate)
}
@Before
fun setup() {
postRepo = mock()
userRepo = mock()
postGateway = mock()
}
@Test
fun `user retrieved on init`() = runBlocking {
val mockUser = mock<UserModel>()
whenever(userRepo.retrieveUser(username)).doReturn(mockUser)
val vm = DisplayUserVM(postRepo, userRepo, postGateway, username)
val observer : Observer<UserModel> = mock()
vm.userLiveData.observeForever(observer)
verify(userRepo, times(1)).retrieveUser(username)
verify(observer).onChanged(mockUser)
}
@Test
fun `livedata updated when posts retrieved` () = runBlocking {
val mockListingItems = listOf<ListingItem>(mock())
val listing = mockListing(mockListingItems)
whenever(postRepo.retrieveUserListing(any(), any(), any())).doReturn(listing)
val tab = UserTab.Saved
val vm = DisplayUserVM(postRepo, userRepo, postGateway, username)
val observer : Observer<List<ListingItem>> = mock()
vm.getTabPostsLiveData(tab).observeForever(observer)
vm.requestPosts(tab, true)
verify(postRepo, times(1)).retrieveUserListing(any(), any(), any())
verify(observer, times(1)).onChanged(mockListingItems)
}
@Test
fun `error livedata updated when no posts retrieved` () = runBlocking {
val listing = mockListing()
val localPostRepo = postRepo
whenever(localPostRepo.retrieveUserListing(any(), any(), any())).doReturn(listing)
val tab = UserTab.Saved
val vm = DisplayUserVM(postRepo, userRepo, postGateway, username)
val listingObserver : Observer<List<ListingItem>> = mock()
vm.getTabPostsLiveData(tab).observeForever(listingObserver)
val errorObserver : Observer<ErrorData> = mock()
vm.errorLiveData.observeForever(errorObserver)
vm.requestPosts(tab, true)
verify(postRepo, times(1)).retrieveUserListing(any(), any(), any())
// listing livedata shouldn't be updated, but an "error" should be posted
verify(listingObserver, never()).onChanged(any())
verify(errorObserver, times(1)).onChanged(ErrorData.NoMorePosts(tab))
}
private fun mockListing(
listingItems : List<ListingItem> = emptyList()
) : Listing<ListingItem> {
val data = Data<ListingItem>().apply {
children = listingItems
}
return Listing(kind = "", data = data)
}
}
答案 0 :(得分:0)
好吧,经过一番阅读之后,我已经更新了代码,以便它使用TestCoroutineDispatcher
而不是newSingleThreadContext()
。我还根据此处的说明https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-test/
@After
fun teardown() {
Dispatchers.resetMain() // reset main dispatcher to the original Main dispatcher
mainThreadSurrogate.cleanupTestCoroutines()
}
测试现在可以成功运行