Как собрать все выбросы из StateFlow в тесте?Android

Форум для тех, кто программирует под Android
Ответить Пред. темаСлед. тема
Anonymous
 Как собрать все выбросы из StateFlow в тесте?

Сообщение Anonymous »

Итак, я хочу проверить логику своей модели представления. Мы используем архитектуру MVI, поэтому у нас есть объект состояния пользовательского интерфейса. Когда происходит определенное событие, viewModel обрабатывает его и обновляет состояние. В моем случае должно быть 3 эмиссии.
Вы можете увидеть пример моей проблемы:
ViewModel:

Код: Выделить всё

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch

class TestViewmodel: ViewModel() {
private val _event = MutableSharedFlow()

private val _state = MutableStateFlow(TestState())
val state = _state.asStateFlow()

init {
viewModelScope.launch {
_event.collect{
handleEvent(it)
}
}
}

private fun handleEvent(event: TestEvent){
if(event == TestEvent.GetData){
getTestData()
}
}

private fun getTestData(){
viewModelScope.launch(Dispatchers.IO){
_state.update {
it.copy(
loading = true
)
}
// delay(100)

val data = getApiData()

_state.update {
it.copy(
loading = false
)
}
// delay(100)

handleApiData(data)
}
}

private fun handleApiData(list: List){
_state.update {
it.copy(
data = list
)
}
}

private suspend fun getApiData(): List{
delay(1000)
return listOf("ffefe","ffefe","fdfdfd")
}

fun setEvent(event: TestEvent){
viewModelScope.launch {
_event.emit(event)
}
}
}

data class TestState(
val loading: Boolean = false,
val data: List = emptyList()
)

sealed interface TestEvent{
data object GetData: TestEvent
}
Тестовый класс:

Код: Выделить всё

import io.kotest.matchers.shouldBe
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.drop
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.test.setMain
import org.junit.jupiter.api.AfterAll
import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestInstance
import org.junit.jupiter.api.extension.ExtendWith

@OptIn(ExperimentalCoroutinesApi::class)
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
class TestViewModelTest(){
private lateinit var viewModel: TestViewmodel

@BeforeAll
fun setUp(){
Dispatchers.setMain(Dispatchers.Unconfined)
viewModel = TestViewmodel()
}

@AfterAll
fun afterAll(){
Dispatchers.resetMain()
}

@Test
fun testEmit() = runTest {
val state = viewModel.state
viewModel.setEvent(TestEvent.GetData)

val result = state.drop(2).first()

result.data.size shouldBe 3
}

@Test
fun testEmitWithTurbine() = runTest {
val state = viewModel.state

state.test {
viewModel.setEvent(TestEvent.GetData)

awaitItem()
awaitItem()
awaitItem().data.size shouldBe 3
}
}

@Test
fun testEmitByGoogle() = runTest {
val state = viewModel.state
val result = mutableListOf()

val collectionJob = launch {
state.toList(result)
}

viewModel.setEvent(TestEvent.GetData)

result[2].data.size shouldBe 3

collectionJob.cancel()
}
}
Итак, моя проблема: когда я пытаюсь протестировать, тест выполняется около 1 минуты, а затем завершается с ошибкой UncompletedCoroutinesError.
Я заметил, что если я ставлю задержку после каждого обновления состояния, тест пройдет успешно, но это не очень хорошее решение.
Я пробовал некоторые идеи из документов Google, но они не сработали. Я не помогу. Хотя тест не завершился с ошибкой UncompletedCoroutinesError, он не пройден. Это не удалось, потому что свойство состояния сохранило только первый эмитент, по крайней мере, так казалось.
Я также пытался использовать библиотеку Turbine, но результат был тот же.
Когда я отлаживал код, я заметил, что утверждение вызывается до того, как произойдет второй/третий выброс. Это объясняет, почему у меня всегда есть только 1 элемент в списке, но я понятия не имею, почему это происходит.< /п>

Подробнее здесь: https://stackoverflow.com/questions/782 ... ow-in-test
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Android»