StateFlow’n ja SharedFlow’n testaaminen Turbinella
Kirjoittakaa Flow-pohjaisen tilan yksikkötestejä Turbine-testauskirjastolla.
StateFlow’n ja SharedFlow’n testaaminen Turbinella on ilmainen Kotlin Academy-oppitunti CoddyKitissä. Tämä on oppitunti 4/4. Voit lukea tästä oppimispolusta kokonaan mitkä tahansa 3 oppituntia ilmaiseksi — sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä käytännön harjoittelun sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Oppitunti kuuluu Kotlin Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Kotlin Academy-kurssilla on yhteensä 4 oppituntia.
Miksi Turbine?
Turbine on Kotlinin Flow-testikirjasto, joka helpottaa emissioiden tarkistamista. Ilman sitä Flow-virtojen testaaminen edellyttää manuaalista kanavan keräämistä aikakatkaisuineen.
// Add to test dependencies:
// testImplementation("app.cash.turbine:turbine:1.0.0")
// testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3")
import app.cash.turbine.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.test.*
fun main() { println("Turbine + runTest = clean flow testing") }Flow-virran perustestaus test()-funktiolla
flow.test { } kerää Flow-virran ja mahdollistaa jokaisen emission tarkistamisen funktioilla awaitItem(), awaitComplete() ja awaitError().
import app.cash.turbine.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.test.*
fun testBasicFlow() = runTest {
val flow = flowOf(1, 2, 3)
flow.test {
assertEquals(1, awaitItem())
assertEquals(2, awaitItem())
assertEquals(3, awaitItem())
awaitComplete()
}
}StateFlow'n testaaminen
StateFlow lähettää nykyisen arvonsa aina, kun sitä aletaan kerätä. Turbinen awaitItem() tallentaa tämän ensimmäisen emission.
import app.cash.turbine.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.test.*
fun testStateFlow() = runTest {
val state = MutableStateFlow("loading")
state.test {
assertEquals("loading", awaitItem()) // initial value
state.value = "success"
assertEquals("success", awaitItem())
cancelAndIgnoreRemainingEvents()
}
}SharedFlow-tapahtumien testaaminen
SharedFlow, jonka asetuksena on replay=0, lähettää vain tulevat tapahtumat. Aloittakaa kerääminen ensin ja lähettäkää tapahtuma vasta sen jälkeen.
import app.cash.turbine.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.test.*
fun testSharedFlow() = runTest {
val events = MutableSharedFlow<String>()
events.test {
events.emit("LoginSuccess")
assertEquals("LoginSuccess", awaitItem())
events.emit("Navigate")
assertEquals("Navigate", awaitItem())
cancelAndIgnoreRemainingEvents()
}
}runTest ja virtuaaliaika
runTest käyttää virtuaaliaikaa — delay()-kutsut siirtävät virtuaaliaikaa välittömästi, joten viiveitä sisältävät testit suoritetaan nopeasti.
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.test.*
import app.cash.turbine.*
fun testDelayedFlow() = runTest {
val flow = flow {
delay(1000) // virtual — runs instantly
emit("done")
}
flow.test {
assertEquals("done", awaitItem())
awaitComplete()
}
}awaitError poikkeusten testaamiseen
awaitError() tarkistaa, että Flow-virta päättyy poikkeukseen. Käyttäkää sitä odotetun poikkeustyypin kanssa.
import app.cash.turbine.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.test.*
fun testFlowError() = runTest {
val flow = flow {
emit(1)
throw RuntimeException("stream error")
}
flow.test {
assertEquals(1, awaitItem())
val error = awaitError()
assertEquals("stream error", error.message)
}
}expectNoEvents ja cancelAndIgnoreRemainingEvents
expectNoEvents() tarkistaa, ettei mitään lähetetty. cancelAndIgnoreRemainingEvents() peruuttaa keräämisen ja ohittaa odottavat emissiot.
import app.cash.turbine.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.test.*
fun testNoEvents() = runTest {
val flow = MutableSharedFlow<Int>()
flow.test {
expectNoEvents() // nothing emitted yet
flow.emit(1)
assertEquals(1, awaitItem())
cancelAndIgnoreRemainingEvents()
}
}ViewModelin testaaminen Turbinella
Testatkaa ViewModelin StateFlow injektoimalla valerepository ja tarkistamalla tilasiirtymät.
import app.cash.turbine.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.test.*
sealed class State { object Loading : State(); data class Data(val v: String) : State() }
class FakeRepo { suspend fun fetch() = "result" }
class VM(repo: FakeRepo, scope: kotlinx.coroutines.CoroutineScope) {
private val _s = MutableStateFlow<State>(State.Loading)
val state = _s.asStateFlow()
init { scope.launch { _s.value = State.Data(repo.fetch()) } }
}
fun testVM() = runTest {
val vm = VM(FakeRepo(), backgroundScope)
vm.state.test {
assertEquals(State.Loading, awaitItem())
val data = awaitItem() as State.Data
assertEquals("result", data.v)
cancelAndIgnoreRemainingEvents()
}
}Useiden kerääjien testaaminen turbineScope-funktiolla
turbineScope { } mahdollistaa useiden Flow-virtojen testaamisen samanaikaisesti siten, että kullakin on oma Turbine-instanssinsa.
import app.cash.turbine.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.test.*
fun testMultipleFlows() = runTest {
val a = MutableStateFlow(1)
val b = MutableStateFlow("x")
turbineScope {
val aTurbine = a.testIn(backgroundScope)
val bTurbine = b.testIn(backgroundScope)
assertEquals(1, aTurbine.awaitItem())
assertEquals("x", bTurbine.awaitItem())
a.value = 2
assertEquals(2, aTurbine.awaitItem())
aTurbine.cancelAndIgnoreRemainingEvents()
bTurbine.cancelAndIgnoreRemainingEvents()
}
}Flow-operaattoreiden testaaminen
Testatkaa mukautettujen Flow-operaattoreiden ja muunnosten toiminta erillään Turbinen avulla.
import app.cash.turbine.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.test.*
fun testOperators() = runTest {
(1..5).asFlow()
.filter { it % 2 == 0 }
.map { it * 10 }
.test {
assertEquals(20, awaitItem())
assertEquals(40, awaitItem())
awaitComplete()
}
}Testaaminen siirtämällä virtuaaliaikaa
Käyttäkää testScheduler.advanceTimeBy()-funktiota virtuaaliajan täsmälliseen hallintaan testeissä, joissa käytetään delay-funktiota.
import app.cash.turbine.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.test.*
fun testTimedFlow() = runTest {
val flow = flow {
emit("start")
delay(500)
emit("end")
}
flow.test {
assertEquals("start", awaitItem())
testScheduler.advanceTimeBy(500)
assertEquals("end", awaitItem())
awaitComplete()
}
}Yleiset virheet
Peruuttakaa Turbine aina kuumien Flow-virtojen testauksen lopuksi. Jos cancelAndIgnoreRemainingEvents() unohtuu, testit jäävät odottamaan uusia tapahtumia.
import app.cash.turbine.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.test.*
fun testGoodPractice() = runTest {
val state = MutableStateFlow(0)
state.test {
awaitItem() // initial 0
state.value = 1
awaitItem() // 1
// Always cancel hot flows:
cancelAndIgnoreRemainingEvents()
}
}Pikatarkistus
Mikä Turbine-funktio kerää seuraavan lähetetyn alkion ja aiheuttaa poikkeuksen, jos Flow-virta päättyy tai epäonnistuu ensin?
Kertaus
Turbine yksinkertaistaa Flow-virtojen testaamista funktioilla awaitItem(), awaitComplete() ja awaitError(). Käyttäkää virtuaaliaikaan runTest-funktiota. Peruuttakaa kuumien Flow-virtojen testit aina funktiolla cancelAndIgnoreRemainingEvents().
Opi Kotlin tekoälytuutorin avulla — ilmaiseksi
Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.
- Kurssit
- 51
- Oppitunnit
- 203
Usein kysytyt kysymykset
Onko oppitunti ”StateFlow’n ja SharedFlow’n testaaminen Turbinella” ilmainen?
Kyllä — voit lukea täällä verkossa kokonaan ilmaiseksi mitkä tahansa Kotlin Academy-oppimispolun 3 oppituntia, myös oppitunnin “StateFlow’n ja SharedFlow’n testaaminen Turbinella”. Sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä interaktiiviset harjoitukset sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Kotlin Academy-kurssilla on yhteensä 4 oppituntia.
Mitä opin oppitunnilla ”StateFlow’n ja SharedFlow’n testaaminen Turbinella”?
Kirjoittakaa Flow-pohjaisen tilan yksikkötestejä Turbine-testauskirjastolla. Harjoittelet Kotlin Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.
Tarvitsenko kokemusta aloittaakseni Kotlin Academy-opiskelun?
Aiempi kokemus ei ole tarpeen. CoddyKitin Kotlin Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 4/4.
Kuinka kauan ”StateFlow’n ja SharedFlow’n testaaminen Turbinella”-oppitunnin suorittaminen kestää?
Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.
Voinko kirjoittaa ja suorittaa koodia tällä Kotlin Academy-oppitunnilla?
Kyllä. Jokainen Kotlin Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.
Kaikki tämän kurssin oppitunnit
- StateFlow: käyttöliittymän hot-tilan säilö
- SharedFlow: tapahtumaväylät ja kertaluonteiset tapahtumat
- Cold Flow -virran muuntaminen hot-virraksi shareIn- ja stateIn-funktioilla
- StateFlow’n ja SharedFlow’n testaaminen Turbinella