无法在ViewModel中测试Livedata
因此,我有这个ViewModel类
@HiltViewModel
class HomeViewModel @Inject constructor(private val starWarsRepository: StarWarsRepository) : ViewModel() {
/**
* Two-Way binding variable
*/
val searchQuery: MutableLiveData<String> = MutableLiveData()
val characters = searchQuery.switchMap { query ->
if (query.isNotBlank() && query.isNotEmpty()) {
characterPager.liveData.cachedIn(viewModelScope)
} else {
MutableLiveData()
}
}
fun retrySearch() {
searchQuery.postValue(searchQuery.value)
}
private val characterPager by lazy {
val searchPagingConfig = PagingConfig(pageSize = 20, maxSize = 100, enablePlaceholders = false)
Pager(config = searchPagingConfig) {
CharacterSearchPagingSource(starWarsRepository, searchQuery.value ?: String())
}
}
}
,这里是反对测试频道,
@ExperimentalCoroutinesApi
@RunWith(JUnit4::class)
class HomeViewModelTest {
@get:Rule
val instantTaskExecutionRule = InstantTaskExecutorRule()
private lateinit var homeViewModel: HomeViewModel
private val starWarsAPI = mock(StarWarsAPI::class.java)
private val testDispatcher = UnconfinedTestDispatcher()
@Before
fun setup() {
Dispatchers.setMain(testDispatcher)
homeViewModel = HomeViewModel(StarWarsRepositoryImpl(starWarsAPI, testDispatcher))
}
@AfterTest
fun tearDown() {
Dispatchers.resetMain()
}
@Test
fun `live data should emit success with result when searching for a character`() = runTest {
val character = CharacterEntity("", "", "", "172", "", listOf(), listOf())
`when`(starWarsAPI.searchCharacters("a", null)).thenReturn(CharacterSearchResultEntity(listOf(character, character), null, null))
homeViewModel.searchQuery.value = "a"
val result = homeViewModel.characters.getOrAwaitValue()
assertEquals(PagingSource.LoadResult.Page(listOf(), null, null), result)
}
}
存储库
class StarWarsRepositoryImpl(private val starWarsAPI: StarWarsAPI, private val coroutineDispatcher: CoroutineDispatcher = Dispatchers.IO) : StarWarsRepository {
override suspend fun searchCharacters(query: String, page: Int?) = withContext(coroutineDispatcher) {
starWarsAPI.searchCharacters(query, page)
}
}
这是我使用的是Google样本中的该扩展功能的
fun <T> LiveData<T>.getOrAwaitValue(time: Long = 2, timeUnit: TimeUnit = TimeUnit.SECONDS, afterObserve: () -> Unit = {}): T {
var data: T? = null
val latch = CountDownLatch(1)
val observer = object : Observer<T> {
override fun onChanged(o: T?) {
data = o
latch.countDown()
[email protected](this)
}
}
this.observeForever(observer)
try {
afterObserve.invoke()
if (!latch.await(time, timeUnit)) {
throw TimeoutException("LiveData value was never set.")
}
} finally {
this.removeObserver(observer)
}
@Suppress("UNCHECKED_CAST")
return data as T
}
。问题是我从getorawaitValue
livedata值从未设置为
?
So, I have this ViewModel class
@HiltViewModel
class HomeViewModel @Inject constructor(private val starWarsRepository: StarWarsRepository) : ViewModel() {
/**
* Two-Way binding variable
*/
val searchQuery: MutableLiveData<String> = MutableLiveData()
val characters = searchQuery.switchMap { query ->
if (query.isNotBlank() && query.isNotEmpty()) {
characterPager.liveData.cachedIn(viewModelScope)
} else {
MutableLiveData()
}
}
fun retrySearch() {
searchQuery.postValue(searchQuery.value)
}
private val characterPager by lazy {
val searchPagingConfig = PagingConfig(pageSize = 20, maxSize = 100, enablePlaceholders = false)
Pager(config = searchPagingConfig) {
CharacterSearchPagingSource(starWarsRepository, searchQuery.value ?: String())
}
}
}
and here it's counter TestingClass
@ExperimentalCoroutinesApi
@RunWith(JUnit4::class)
class HomeViewModelTest {
@get:Rule
val instantTaskExecutionRule = InstantTaskExecutorRule()
private lateinit var homeViewModel: HomeViewModel
private val starWarsAPI = mock(StarWarsAPI::class.java)
private val testDispatcher = UnconfinedTestDispatcher()
@Before
fun setup() {
Dispatchers.setMain(testDispatcher)
homeViewModel = HomeViewModel(StarWarsRepositoryImpl(starWarsAPI, testDispatcher))
}
@AfterTest
fun tearDown() {
Dispatchers.resetMain()
}
@Test
fun `live data should emit success with result when searching for a character`() = runTest {
val character = CharacterEntity("", "", "", "172", "", listOf(), listOf())
`when`(starWarsAPI.searchCharacters("a", null)).thenReturn(CharacterSearchResultEntity(listOf(character, character), null, null))
homeViewModel.searchQuery.value = "a"
val result = homeViewModel.characters.getOrAwaitValue()
assertEquals(PagingSource.LoadResult.Page(listOf(), null, null), result)
}
}
Here is the repository
class StarWarsRepositoryImpl(private val starWarsAPI: StarWarsAPI, private val coroutineDispatcher: CoroutineDispatcher = Dispatchers.IO) : StarWarsRepository {
override suspend fun searchCharacters(query: String, page: Int?) = withContext(coroutineDispatcher) {
starWarsAPI.searchCharacters(query, page)
}
}
I'm using this extension function from a google sample.
fun <T> LiveData<T>.getOrAwaitValue(time: Long = 2, timeUnit: TimeUnit = TimeUnit.SECONDS, afterObserve: () -> Unit = {}): T {
var data: T? = null
val latch = CountDownLatch(1)
val observer = object : Observer<T> {
override fun onChanged(o: T?) {
data = o
latch.countDown()
[email protected](this)
}
}
this.observeForever(observer)
try {
afterObserve.invoke()
if (!latch.await(time, timeUnit)) {
throw TimeoutException("LiveData value was never set.")
}
} finally {
this.removeObserver(observer)
}
@Suppress("UNCHECKED_CAST")
return data as T
}
The problem is I'm getting an exception from the getOrAwaitValue
that LiveData value was never set.
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论