Eşlikler kullanan birim testi kodu, yürütme eşzamansız olarak gerçekleştirilebileceği ve birden fazla iş parçacığında gerçekleşebileceği için ekstra dikkat gerektirir. Bu kılavuzda, askıya alma işlevlerinin nasıl test edilebileceği, bilmeniz gereken test yapıları ve eş yordamları kullanan kodunuzu nasıl test edilebilir hale getirebileceğiniz ele alınmaktadır.
Bu kılavuzda kullanılan API'ler, kotlinx.coroutines.test kitaplığının bir parçasıdır. Bu API'lere erişmek için yapıyı projenize bir test bağımlılığı olarak eklediğinizden emin olun.
dependencies {
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version"
}
Testlerde askıya alma işlevleri çağırma
Testlerde askıya alma işlevlerini çağırmak için bir eş yordamda olmanız gerekir. JUnit test işlevlerinin kendileri işlevleri askıya almadığından, yeni bir eş yordam başlatmak için testlerinizin içinde bir eş yordam oluşturucu çağırmanız gerekir.
runTest
, test için tasarlanmış bir eş yordam oluşturucudur. Eş yordam içeren tüm testleri sarmalamak için bunu kullanın. Eş yordamların yalnızca doğrudan test gövdesinde değil, testte kullanılan nesneler tarafından da başlatılabileceğini unutmayın.
suspend fun fetchData(): String { delay(1000L) return "Hello world" } @Test fun dataShouldBeHelloWorld() = runTest { val data = fetchData() assertEquals("Hello world", data) }
Genel olarak, test başına bir runTest
çağrınız olmalıdır ve bir ifade gövdesi kullanmanız önerilir.
Testinizin kodunu runTest
içinde sarmalamak, temel askıya alma işlevlerini test etmek için işe yarar ve eş yordamlardaki gecikmeleri otomatik olarak atlayarak yukarıdaki testin bir saniyeden çok daha kısa sürede tamamlanmasını sağlar.
Ancak, test edilen kodunuzda ne olduğuna bağlı olarak dikkat etmeniz gereken bazı ek noktalar vardır:
- Kodunuz,
runTest
tarafından oluşturulan üst düzey test eş yordamı dışında yeni eş yordamlar oluşturduğunda, uygunTestDispatcher
'yi seçerek bu yeni eş yordamların nasıl planlandığını kontrol etmeniz gerekir. - Kodunuz eş yordam yürütmesini başka görev dağıtıcılara taşırsa (örneğin,
withContext
kullanarak)runTest
genel olarak çalışmaya devam eder ancak artık gecikmeler atlanmaz ve kod birden fazla iş parçacığında çalıştırıldığından testler daha az tahmin edilebilir olur. Bu nedenlerden dolayı, testlerde gerçek görev dağıtıcıları değiştirmek için test görev dağıtıcıları eklemeniz gerekir.
Test Sevk görevlileri
TestDispatchers
, test amaçlı CoroutineDispatcher
uygulamalarıdır. Yeni eş yordamların yürütülmesini tahmin edilebilir hale getirmek için test sırasında yeni eş yordalar oluşturulursa TestDispatchers
kullanmanız gerekir.
TestDispatcher
için kullanılabilen iki uygulama vardır: StandardTestDispatcher
ve UnconfinedTestDispatcher
. Bu uygulamalar, yeni başlatılan ortaklar için farklı planlamalar yapar. Her ikisi de sanal zamanı kontrol etmek ve bir test sırasında çalışan eşleri yönetmek için bir TestCoroutineScheduler
kullanır.
Bir testte yalnızca bir planlayıcı örneği kullanılmalıdır ve TestDispatchers
bunların tümü arasında paylaşılır. Planlayıcıları paylaşma hakkında bilgi edinmek için TestDispatchers Ekleme başlıklı makaleye bakın.
runTest
, üst düzey test eş yordamını başlatmak için bir TestScope
oluşturur. Bu, her zaman TestDispatcher
kullanacak olan bir CoroutineScope
uygulamasıdır. Belirtilmezse TestScope
varsayılan olarak bir StandardTestDispatcher
oluşturur ve üst düzey test eş yordamını çalıştırmak için bunu kullanır.
runTest
, TestScope
görev dağıtıcısı tarafından kullanılan planlayıcıda sıraya alınan eş değerleri takip eder ve ilgili planlayıcıda beklemede olan çalışmalar olduğu sürece geri gelmez.
StandartTestDispatcher
Bir StandardTestDispatcher
üzerinde yeni eş yordamlar başlattığınızda bu eş postalar, test iş parçacığı serbest olduğunda çalıştırılmak üzere temel planlayıcıda sıraya alınır. Bu yeni eş yordamların çalışmasına izin vermek için test iş parçacığını getirmeniz gerekir (diğer eş yapılandırmaları kullanması için serbest bırakın). Bu sıraya alma davranışı, test sırasında yeni eş yordamların nasıl çalışacağı üzerinde hassas bir kontrole sahip olmanızı sağlar ve üretim kodundaki eş yordamların programlanmasına benzer.
Üst düzey test eş yordasının yürütülmesi sırasında test iş parçacığı hiçbir zaman sağlanmazsa yeni eş yordamlar yalnızca test eş yordasının tamamlanmasından sonra (ancak runTest
geri dönmeden önce) çalışır:
@Test fun standardTest() = runTest { val userRepo = UserRepository() launch { userRepo.register("Alice") } launch { userRepo.register("Bob") } assertEquals(listOf("Alice", "Bob"), userRepo.getAllUsers()) // ❌ Fails }
Sıraya alınan eş yordamların çalışmasını sağlamak için test eş yordamının birkaç yolu vardır. Bu çağrıların tümü, geri dönmeden önce diğer eş yordamlarının test ileti dizisinde çalıştırılmasını sağlar:
advanceUntilIdle
: Sırada hiçbir şey kalmayana kadar diğer tüm eş yordamları planlayıcıda çalıştırır. Bu, bekleyen tüm eş yordamların çalışmasına izin vermek için iyi bir varsayılan seçenektir ve çoğu test senaryosunda işe yarar.advanceTimeBy
: Sanal zamanı belirtilen miktara göre ilerletir ve sanal zamandaki bu noktadan önce çalıştırılmak üzere planlanmış eş yordamları çalıştırır.runCurrent
: Geçerli sanal saatte planlanmış eş yordamlar çalıştırır.
Önceki testi düzeltmek amacıyla, onaylamaya devam etmeden önce beklemedeki iki eş yordamın çalışmasını sağlamak için advanceUntilIdle
kullanılabilir:
@Test fun standardTest() = runTest { val userRepo = UserRepository() launch { userRepo.register("Alice") } launch { userRepo.register("Bob") } advanceUntilIdle() // Yields to perform the registrations assertEquals(listOf("Alice", "Bob"), userRepo.getAllUsers()) // ✅ Passes }
Sınırsız Test Görevlisi
Bir UnconfinedTestDispatcher
üzerinde yeni eş yordamlar başlatıldığında heyecanla mevcut ileti dizisinde başlatılır. Diğer bir deyişle, eş yordam oluşturucunun geri dönmesini beklemeden hemen çalışmaya başlarlar. Çoğu durumda, bu gönderme davranışı daha basit bir test kodu ile sonuçlanır. Yeni eş yapılandırmaları çalıştırmak için test iş parçacığını manuel olarak oluşturmanız gerekmez.
Ancak bu davranış, test dışı görev dağıtıcılarla üretimde göreceğiniz davranıştan farklıdır. Testiniz eşzamanlılığa odaklanıyorsa bunun yerine StandardTestDispatcher
kullanmayı tercih edin.
Bu görev dağıtıcıyı runTest
öğesindeki üst düzey test eş yordamı için varsayılan eş yordam yerine kullanmak üzere bir örnek oluşturun ve parametre olarak iletin. Bu işlem, runTest
içinde oluşturulan yeni eş yordamlarının, görev dağıtıcıyı TestScope
öğesinden devraldığı için istekle yürütülmesini sağlar.
@Test fun unconfinedTest() = runTest(UnconfinedTestDispatcher()) { val userRepo = UserRepository() launch { userRepo.register("Alice") } launch { userRepo.register("Bob") } assertEquals(listOf("Alice", "Bob"), userRepo.getAllUsers()) // ✅ Passes }
Bu örnekte, lansman çağrıları yeni eş yordamlarını UnconfinedTestDispatcher
üzerinde heyecanla başlatacaktır. Diğer bir deyişle, her başlatma çağrısı yalnızca kayıt tamamlandıktan sonra geri dönecektir.
UnconfinedTestDispatcher
ürününün yeni eş yordamları hevesle başlatacağını unutmayın. Ancak bu, eş zamanlı programların tamamlanması için onları da istekle çalıştıracağı anlamına gelmez. Yeni eş yordam askıya alınırsa diğer eş yordamlar yürütülmeye devam eder.
Örneğin, bu testte başlatılan yeni eş yordam Ayşe'yi kaydeder, ancak delay
çağrıldığında askıya alınır. Bu, üst düzey eş yordamın onaylamaya devam etmesini sağlar ve İbrahim henüz kayıtlı olmadığından test başarısız olur:
@Test fun yieldingTest() = runTest(UnconfinedTestDispatcher()) { val userRepo = UserRepository() launch { userRepo.register("Alice") delay(10L) userRepo.register("Bob") } assertEquals(listOf("Alice", "Bob"), userRepo.getAllUsers()) // ❌ Fails }
Test görev dağıtıcıları ekleme
Test edilen kod, ileti dizilerini değiştirmek (withContext
ile) veya yeni eş postalar başlatmak için görev dağıtıcıları kullanabilir. Kod paralel olarak birden fazla iş parçacığında yürütüldüğünde testler güvenilir olmayabilir. Onayları doğru zamanda gerçekleştirmek veya kontrol sahibi olmadığınız arka plan ileti dizilerinde çalışıyorsa görevlerin tamamlanmasını beklemek zor olabilir.
Testlerde, bu görev dağıtıcıları TestDispatchers
örnekleriyle değiştirin. Bunun pek çok avantajı vardır:
- Kod, tek test iş parçacığında çalışacak ve böylece testleri daha belirleyici hale getirecektir
- Yeni eş yordamların nasıl planlandığını ve yürütüleceğini kontrol edebilirsiniz
- TestDispatchers, sanal zaman için gecikmeleri otomatik olarak atlayan ve zamanı manuel olarak ilerletmenizi sağlayan bir planlayıcı kullanır
Sınıflarınıza sevk görevlileri sağlamak için bağımlılık ekleme özelliğini kullanmak, testlerdeki gerçek görev dağıtıcıları değiştirmeyi kolaylaştırır. Bu örneklerde bir CoroutineDispatcher
ekleyeceğiz ama testler sırasında daha da fazla esneklik sağlamak için daha geniş olan CoroutineContext
türünü de ekleyebilirsiniz.
Eş yordamlar başlatan sınıflar için, Kapsam ekleme bölümünde ayrıntılı olarak açıklandığı gibi, bir görev dağıtıcı yerine CoroutineScope
de ekleyebilirsiniz.
TestDispatchers
, örneklendiğinde varsayılan olarak yeni bir zamanlayıcı oluşturur. runTest
içinde, TestScope
öğesinin testScheduler
mülküne erişebilir ve bunu yeni oluşturulan TestDispatchers
öğesine aktarabilirsiniz. Bu, sanal zamanla ilgili anlayışlarını paylaşır ve advanceUntilIdle
gibi yöntemler, testin tamamlanması için tüm test görev dağıtıcılarında eş yordamlar çalıştırır.
Aşağıdaki örnekte, initialize
yöntemindeki IO
görev dağıtıcısını kullanarak yeni bir eş yordam oluşturan ve fetchData
yönteminde çağrıyı IO
görev dağıtıcısına geçiren bir Repository
sınıfını görebilirsiniz:
// Example class demonstrating dispatcher use cases class Repository(private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO) { private val scope = CoroutineScope(ioDispatcher) val initialized = AtomicBoolean(false) // A function that starts a new coroutine on the IO dispatcher fun initialize() { scope.launch { initialized.set(true) } } // A suspending function that switches to the IO dispatcher suspend fun fetchData(): String = withContext(ioDispatcher) { require(initialized.get()) { "Repository should be initialized first" } delay(500L) "Hello world" } }
Testlerde, IO
görev dağıtıcısının yerine bir TestDispatcher
uygulaması ekleyebilirsiniz.
Aşağıdaki örnekte, kod deposuna bir StandardTestDispatcher
yerleştirme ve initialize
içinde başlatılan yeni eş yordamın devam etmeden önce tamamlandığından emin olmak için advanceUntilIdle
kullanıyoruz.
Test ileti dizisinde çalıştırılacağı ve test sırasında içerdiği gecikmeyi atlayacağı için fetchData
parametresi de bir TestDispatcher
üzerinde çalıştırmaktan faydalanabilir.
class RepositoryTest { @Test fun repoInitWorksAndDataIsHelloWorld() = runTest { val dispatcher = StandardTestDispatcher(testScheduler) val repository = Repository(dispatcher) repository.initialize() advanceUntilIdle() // Runs the new coroutine assertEquals(true, repository.initialized.get()) val data = repository.fetchData() // No thread switch, delay is skipped assertEquals("Hello world", data) } }
TestDispatcher
üzerinde başlatılan yeni eş yordamlar, yukarıda initialize
ile gösterildiği gibi manuel olarak geliştirilebilir. Ancak üretim kodunda bunun mümkün olmadığını ve istenmeyeceğini unutmayın. Bunun yerine bu yöntem, askıya alma (sıralı yürütme için) veya bir Deferred
değeri (eşzamanlı yürütme için) döndürecek şekilde yeniden tasarlanmalıdır.
Örneğin, yeni bir eş yordam başlatmak ve bir Deferred
oluşturmak için async
aracını kullanabilirsiniz:
class BetterRepository(private val ioDispatcher: CoroutineDispatcher = Dispatchers.IO) { private val scope = CoroutineScope(ioDispatcher) fun initialize() = scope.async { // ... } }
Böylece hem testlerde hem de üretim kodunda bu kodun tamamlanmasını güvenli bir şekilde await
yapabilirsiniz:
@Test fun repoInitWorks() = runTest { val dispatcher = StandardTestDispatcher(testScheduler) val repository = BetterRepository(dispatcher) repository.initialize().await() // Suspends until the new coroutine is done assertEquals(true, repository.initialized.get()) // ... }
Ortaklar, planlayıcıyı paylaştığı bir TestDispatcher
üzerindeyse runTest
dönmeden önce bekleyen eş yordalarının tamamlanmasını bekler. Ayrıca, diğer görev dağıtıcılarda olsalar bile üst düzey test eş yordasının alt öğeleri olan eş yordamları da bekler (dispatchTimeoutMs
parametresi tarafından belirtilen zaman aşımı varsayılan olarak 60 saniyeye kadar).
Ana görev dağıtıcıyı ayarlama
Yerel birim testlerinde, Android kullanıcı arayüzü iş parçacığını saran Main
görev dağıtıcısı, bu testler bir Android cihazda değil, yerel bir JVM'de yürütüldüğünden kullanılamaz. Test edilen kodunuz ana iş parçacığına referans veriyorsa birim testleri sırasında bir istisna oluşturur.
Bazı durumlarda, Main
görev dağıtıcısını önceki bölümde açıklandığı gibi, diğer görev dağıtıcılarla aynı şekilde yerleştirebilir ve testlerde bir TestDispatcher
ile değiştirebilirsiniz. Ancak, viewModelScope
gibi bazı API'ler, arka planda sabit kodlu bir Main
görev dağıtıcısı kullanır.
Veri yükleyen bir eş yordamı başlatmak için viewModelScope
kullanan bir ViewModel
uygulaması örneğini burada bulabilirsiniz:
class HomeViewModel : ViewModel() { private val _message = MutableStateFlow("") val message: StateFlow<String> get() = _message fun loadMessage() { viewModelScope.launch { _message.value = "Greetings!" } } }
Main
görev dağıtıcısını her durumda TestDispatcher
ile değiştirmek için Dispatchers.setMain
ve Dispatchers.resetMain
işlevlerini kullanın.
class HomeViewModelTest { @Test fun settingMainDispatcher() = runTest { val testDispatcher = UnconfinedTestDispatcher(testScheduler) Dispatchers.setMain(testDispatcher) try { val viewModel = HomeViewModel() viewModel.loadMessage() // Uses testDispatcher, runs its coroutine eagerly assertEquals("Greetings!", viewModel.message.value) } finally { Dispatchers.resetMain() } } }
Main
görev dağıtıcısı TestDispatcher
ile değiştirildiyse yeni oluşturulan tüm TestDispatchers
, otomatik olarak Main
görev dağıtıcısındaki planlayıcıyı kullanacaktır. Buna, başka görev dağıtıcı iletilmezse runTest
tarafından oluşturulan StandardTestDispatcher
de dahildir.
Bu, test sırasında yalnızca tek bir planlayıcının kullanılmasını kolaylaştırır. Bunu gerçekleştirmek için Dispatchers.setMain
çağırdıktan sonra diğer tüm TestDispatcher
örneklerini oluşturduğunuzdan emin olun.
Her testte Main
görev dağıtıcısının yerini alan kodun yinelenmesini önlemek için yaygın olarak kullanılan bir yöntem, kodu bir JUnit test kuralına çıkarmaktır:
// Reusable JUnit4 TestRule to override the Main dispatcher class MainDispatcherRule( val testDispatcher: TestDispatcher = UnconfinedTestDispatcher(), ) : TestWatcher() { override fun starting(description: Description) { Dispatchers.setMain(testDispatcher) } override fun finished(description: Description) { Dispatchers.resetMain() } } class HomeViewModelTestUsingRule { @get:Rule val mainDispatcherRule = MainDispatcherRule() @Test fun settingMainDispatcher() = runTest { // Uses Main’s scheduler val viewModel = HomeViewModel() viewModel.loadMessage() assertEquals("Greetings!", viewModel.message.value) } }
Bu kural uygulaması, varsayılan olarak bir UnconfinedTestDispatcher
kullanır. Ancak Main
görev dağıtıcısının belirli bir test sınıfında hızlı bir şekilde yürütülmemesi gerekiyorsa parametre olarak StandardTestDispatcher
geçirilebilir.
Test gövdesinde bir TestDispatcher
örneğine ihtiyacınız olduğunda, istenen tür olduğu sürece kuraldaki testDispatcher
öğesini yeniden kullanabilirsiniz. Testte kullanılan TestDispatcher
türünü açıkça belirtmek istiyorsanız veya Main
için kullanılandan farklı bir TestDispatcher
türüne ihtiyacınız varsa runTest
içinde yeni bir TestDispatcher
oluşturabilirsiniz. Main
görev dağıtıcısı TestDispatcher
olarak ayarlandığından, yeni oluşturulan tüm TestDispatchers
planlayıcısını otomatik olarak paylaşacaktır.
class DispatcherTypesTest { @get:Rule val mainDispatcherRule = MainDispatcherRule() @Test fun injectingTestDispatchers() = runTest { // Uses Main’s scheduler // Use the UnconfinedTestDispatcher from the Main dispatcher val unconfinedRepo = Repository(mainDispatcherRule.testDispatcher) // Create a new StandardTestDispatcher (uses Main’s scheduler) val standardRepo = Repository(StandardTestDispatcher()) } }
Testin dışında görev dağıtıcıları oluşturma
Bazı durumlarda, test yönteminin dışında bir TestDispatcher
sunulması gerekebilir. Örneğin, test sınıfındaki bir özelliğin başlatılması sırasında:
class Repository(private val ioDispatcher: CoroutineDispatcher) { /* ... */ } class RepositoryTestWithRule { private val repository = Repository(/* What TestDispatcher? */) @get:Rule val mainDispatcherRule = MainDispatcherRule() @Test fun someRepositoryTest() = runTest { // Test the repository... // ... } }
Önceki bölümde gösterildiği gibi Main
görev dağıtıcısını değiştiriyorsanız Main
görev dağıtıcısı değiştirildikten sonra oluşturulan TestDispatchers
, planlayıcısını otomatik olarak paylaşır.
Ancak bu durum, test sınıfının özellikleri olarak oluşturulan TestDispatchers
veya test sınıfındaki özelliklerin başlatılması sırasında oluşturulan TestDispatchers
için geçerli değildir. Bunlar, Main
görev dağıtıcısı değiştirilmeden önce başlatılır. Bu nedenle, yeni planlayıcılar oluştururlar.
Testinizde yalnızca bir planlayıcı olduğundan emin olmak için önce MainDispatcherRule
özelliğini oluşturun. Ardından, görev dağıtıcısını (veya farklı türde bir TestDispatcher
öğesine ihtiyacınız varsa planlayıcısını) diğer sınıf düzeyindeki özelliklerin başlatıcılarında gerektiğinde yeniden kullanın.
class RepositoryTestWithRule { @get:Rule val mainDispatcherRule = MainDispatcherRule() private val repository = Repository(mainDispatcherRule.testDispatcher) @Test fun someRepositoryTest() = runTest { // Takes scheduler from Main // Any TestDispatcher created here also takes the scheduler from Main val newTestDispatcher = StandardTestDispatcher() // Test the repository... } }
Test sırasında oluşturulan runTest
ve TestDispatchers
öğelerinin, Main
görev dağıtıcısının planlayıcısını otomatik olarak paylaşmaya devam edeceğini unutmayın.
Main
görev dağıtıcısını değiştirmiyorsanız sınıfın özelliği olarak ilk TestDispatcher
oluşturun (yeni bir planlayıcı oluşturur). Ardından, bu planlayıcıyı hem mülk olarak hem de test içinde her runTest
çağrısına ve oluşturulan her yeni TestDispatcher
öğesine manuel olarak iletin:
class RepositoryTest { // Creates the single test scheduler private val testDispatcher = UnconfinedTestDispatcher() private val repository = Repository(testDispatcher) @Test fun someRepositoryTest() = runTest(testDispatcher.scheduler) { // Take the scheduler from the TestScope val newTestDispatcher = UnconfinedTestDispatcher(this.testScheduler) // Or take the scheduler from the first dispatcher, they’re the same val anotherTestDispatcher = UnconfinedTestDispatcher(testDispatcher.scheduler) // Test the repository... } }
Bu örnekte, ilk görev dağıtıcıdaki planlayıcı runTest
öğesine iletilir. Bu işlem, söz konusu planlayıcıyı kullanarak TestScope
için yeni bir StandardTestDispatcher
oluşturur. Ayrıca, sevk görevlisinde test eş yordasını çalıştırmak için görev dağıtıcıyı doğrudan runTest
bölümüne geçirebilirsiniz.
Kendi TestScope'unuzu oluşturma
TestDispatchers
'da olduğu gibi, test gövdesinin dışında bir TestScope
öğesine erişmeniz gerekebilir. runTest
, arka planda otomatik olarak bir TestScope
oluşturur. Bununla birlikte, runTest
ile kullanmak üzere kendi TestScope
öğenizi de oluşturabilirsiniz.
Bunu yaparken, oluşturduğunuz TestScope
cihazında runTest
numarasını aradığınızdan emin olun:
class SimpleExampleTest { val testScope = TestScope() // Creates a StandardTestDispatcher @Test fun someTest() = testScope.runTest { // ... } }
Yukarıdaki kod, TestScope
için dolaylı yoldan bir StandardTestDispatcher
ve yeni bir planlayıcı oluşturur. Bu nesnelerin tümü açık bir şekilde de oluşturulabilir. Bu işlem, bağımlı yerleştirme kurulumlarıyla entegre etmeniz gerekiyorsa yararlı olabilir.
class ExampleTest { val testScheduler = TestCoroutineScheduler() val testDispatcher = StandardTestDispatcher(testScheduler) val testScope = TestScope(testDispatcher) @Test fun someTest() = testScope.runTest { // ... } }
Kapsam ekleme
Testler sırasında kontrol etmeniz gereken eş yordamlar oluşturan bir sınıfınız varsa ilgili sınıfa eş yordam kapsamını ekleyebilir ve testlerde TestScope
ile değiştirebilirsiniz.
Aşağıdaki örnekte UserState
sınıfı, yeni kullanıcıları kaydetmek ve kayıtlı kullanıcıların listesini getirmek için bir UserRepository
kullanıyor. Bu UserRepository
çağrıları işlev çağrılarını askıya aldığından, UserState
yerleştirilen CoroutineScope
öğesini kullanarak registerUser
işlevi içinde yeni bir eş yordamı başlatır.
class UserState( private val userRepository: UserRepository, private val scope: CoroutineScope, ) { private val _users = MutableStateFlow(emptyList<String>()) val users: StateFlow<List<String>> = _users.asStateFlow() fun registerUser(name: String) { scope.launch { userRepository.register(name) _users.update { userRepository.getAllUsers() } } } }
Bu sınıfı test etmek için UserState
nesnesini oluştururken runTest
öğesinden TestScope
öğesini geçirebilirsiniz:
class UserStateTest { @Test fun addUserTest() = runTest { // this: TestScope val repository = FakeUserRepository() val userState = UserState(repository, scope = this) userState.registerUser("Mona") advanceUntilIdle() // Let the coroutine complete and changes propagate assertEquals(listOf("Mona"), userState.users.value) } }
Test işlevinin dışına, örneğin test sınıfında bir özellik olarak oluşturulan test kapsamındaki bir nesneye bir kapsam eklemek için Kendi TestKapsamınızı oluşturma bölümüne bakın.