Kotlin Academy · Ders

Turbine ile StateFlow ve SharedFlow Sınaması

Turbine sınama kütüphanesini kullanarak Flow tabanlı durum için birim sınamaları yazın.

4. ders / 414 adım

Turbine ile StateFlow ve SharedFlow Sınaması, CoddyKit'te ücretsiz bir Kotlin Academy dersidir. Bu, 4 dersinin 4. dersidir. Aşağıdan dersin tamamını ücretsiz okuyabilir, sonra tarayıcıda yerleşik kod editörü ve 7/24 yapay zeka koçu ile uygulamalı olarak pratik yapabilirsin. Bu, Kotlin Academy öğrenme yolunun bir parçasıdır ve ilerlemeniz web ve CoddyKit uygulaması arasında senkronize olur. Kotlin Academy kursu toplamda 4 dersten oluşur.

Neden Turbine?

Turbine, Kotlin akışları için yayınları doğrulamayı kolaylaştıran bir sınama kitaplığıdır. Bu kitaplık olmadan akışları sınamak, zaman aşımlarıyla kanal toplamayı elle yönetmeyi gerektirir.

// 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") }

test() ile Temel Akış Sınaması

flow.test { }, akışı toplar ve her yayını awaitItem(), awaitComplete() ve awaitError() kullanarak doğrulamanızı sağlar.

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 Sınaması

StateFlow, toplandığında her zaman geçerli değerini yayınlar. Turbine'ın awaitItem() işlevi bu ilk yayını yakalar.

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 Olaylarını Sınama

replay=0 olan SharedFlow yalnızca gelecekteki olayları yayınlar. Önce toplamaya başlayın, ardından yayınlayın.

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()
    }
}

Sanal Zaman için runTest

runTest sanal zamanı kullanır — delay() çağrıları sanal zamanı anında ilerleterek gecikmeli sınamaları hızlandırır.

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()
    }
}

Özel Durum Sınaması için awaitError

awaitError(), akışın bir özel durumla sonlandığını doğrular. Bunu beklenen özel durum türüyle birlikte kullanın.

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 ve cancelAndIgnoreRemainingEvents

expectNoEvents(), hiçbir şey yayınlanmadığını doğrular. cancelAndIgnoreRemainingEvents(), bekleyen yayınları yok sayarak toplamayı iptal eder.

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()
    }
}

ViewModel'i Turbine ile Sınama

Bir ViewModel'in StateFlow'unu sahte bir depo enjekte ederek ve durum geçişlerini doğrulayarak sınayın.

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()
    }
}

turbineScope ile Birden Çok Toplayıcı

turbineScope { }, her biri kendi Turbine örneğine sahip olacak şekilde birden çok akışı eşzamanlı olarak sınamanızı sağlar.

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()
    }
}

Akış İşleçlerini Sınama

Özel akış işleçlerinin ve dönüşümlerinin davranışını Turbine kullanarak yalıtılmış biçimde sınayın.

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()
        }
}

Sahte Zaman İlerlemesiyle Sınama

testScheduler.advanceTimeBy() kullanarak delay içeren sınamalarda sanal zamanı kesin biçimde denetleyin.

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()
    }
}

Yaygın Hatalar

Sıcak akış sınamalarının sonunda Turbine'ı her zaman iptal edin. cancelAndIgnoreRemainingEvents() çağrısını unutmak, daha fazla olay beklerken sınamaların takılı kalmasına neden olur.

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()
    }
}

Hızlı Kontrol

Bir sonraki yayınlanan öğeyi toplayan ve akış önce tamamlanır ya da hata verirse özel durum oluşturan Turbine işlevi hangisidir?

Özet

Turbine, awaitItem(), awaitComplete() ve awaitError() ile akış sınamasını kolaylaştırır. Sanal zaman için runTest kullanın. Sıcak akış sınamalarını her zaman cancelAndIgnoreRemainingEvents() ile iptal edin.

Başlamak ücretsiz

Yapay zeka eğitmeniyle Kotlin öğren — ücretsiz

Tarayıcında gerçek kod yaz ve çalıştır, 7/24 yapay zeka eğitmeninden anında yardım al; web'de ya da uygulamada kaldığın yerden devam et.

Kurslar
51
Dersler
203

Sıkça Sorulan Sorular

“Turbine ile StateFlow ve SharedFlow Sınaması” dersi ücretsiz mi?

Evet — “Turbine ile StateFlow ve SharedFlow Sınaması” dersin tüm metni burada web'de ücretsiz olarak okunabilir. Etkileşimli olarak pratik yapmak (yerleşik kod editörü ve 7/24 yapay zeka koçu) ve Kotlin Academy kursunun geri kalanını açmak için CoddyKit PRO'ya yükselt. Kotlin Academy kursu toplamda 4 dersten oluşur.

“Turbine ile StateFlow ve SharedFlow Sınaması” dersinde ne öğreneceğim?

Turbine sınama kütüphanesini kullanarak Flow tabanlı durum için birim sınamaları yazın. Kotlin Academy ile uygulamalı kodu tarayıcıda doğrudan çalıştırarak pratik yaparsın ve 7/24 yapay zeka koçu dersi çalışırken sorularını yanıtlar.

Kotlin Academy öğrenmeye başlamak için deneyim gerekli mi?

Önceden deneyim gerekmez. CoddyKit'te Kotlin Academy, başlangıçtan ileri seviyeye kadar yapılandırıldığı için buradan başlayabilir veya başından başlayıp kendi hızında ilerleme yapabilirsin. Bu, 4 dersinin 4. dersidir.

“Turbine ile StateFlow ve SharedFlow Sınaması” dersi ne kadar sürer?

Çoğu CoddyKit dersi yaklaşık 5–10 dakika sürer. Her biri kısa ve etkileşimli olduğu için sabit ilerleme yaparsın ve web ile uygulama arasında tam olarak bıraktığın yerden devam edebilirsin.

Bu Kotlin Academy dersinde kod yazıp çalıştırabilir miyim?

Evet. Her Kotlin Academy dersi yerleşik bir kod editörü içerir, bu sayede tarayıcıda gerçek kod yazıp çalıştırabilir ve anlık yapay zeka geri bildirimi alırsın — yerel kurulum gerekli değildir.

Bu kursun tüm dersleri

  1. StateFlow: Kullanıcı Arayüzü için Sıcak Durum Tutucusu
  2. SharedFlow: Olay Veri Yolları ve Tek Seferlik Olaylar
  3. shareIn ve stateIn ile Soğuk Flow'u Sıcağa Dönüştürme
  4. Turbine ile StateFlow ve SharedFlow Sınaması
← Kotlin Academy Sayfasına Dön