Test Doubles — yedek nesne türleri ve kullanımı

Yazar: IT Sectr Yayınlanma: 2026-04-10 Okuma süresi: 9 dk

Test Doubles, birim testlerde gerçek bağımlılıklar yerine kullanılan yedek nesnelerdir. Terim, Gerard Meszaros tarafından “xUnit Test Patterns” (2007) kitabında Mock, Stub, Fake, Spy ve Dummy için genel bir kavram olarak tanıtılmıştır. Martin Fowler (2024)'a göre, Test Doubles test edilen bileşeni ortamından izole ederek testlerin deterministik, hızlı ve harici hizmetlerden bağımsız olmasını sağlar.

Önemli Noktalar

  • Test Doubles — testlerdeki tüm yedek nesne türleri için genel terim
  • Mock etkileşimi doğrular: hangi metotların hangi argümanlarla çağrıldığı
  • Stub çağrıları doğrulamadan önceden tanımlanmış değerler döndürür
  • Fake — basitleştirilmiş çalışan uygulama (örn., bellek içi veritabanı)
  • Spy sonraki doğrulama için çağrıları kaydeder, Dummy parametreleri doldurur

Test Doubles Nedir?

Test Doubles otomotiv endüstrisinden (dublör) yazılım geliştirmeye aktarılmış bir terimdir. Bir dublörün tehlikeli bir sahnede aktörün yerini alması gibi, Test Double da bir test senaryosunda gerçek bileşenin yerini alır. Bu, gerçek bağımlılık kullanılamadığında, yavaş olduğunda, deterministik olmadığında veya yan etkileri olduğunda gereklidir.

Test Double kavramı beş belirli türü kapsar ve her biri kendi görevini çözer. Meszaros tipolojisi kanoniktir ve tüm modern test kılavuzlarında kullanılır. Türler arasındaki fark, kontrol ve doğrulama derecesinde yatar: basit parametre doldurmadan (Dummy) tam çağrı sırası doğrulamasına (Mock) kadar.

Test Doubles Neden Gereklidir

Test Doubles'ın ana amacı, test edilen modülün izole edilmesidir. Mobil geliştirmede, gerçek bağımlılıklar API sunucuları, veritabanları, dosya sistemi, cihaz sensörleri ve sistem hizmetlerini (LocationManager, Camera, Bluetooth) içerir. Bu bileşenleri doğrudan kullanmak testleri yavaş, kırılgan ve ortama bağımlı hale getirir. Google Testing Blog (2023)'e göre, iyi izole edilmiş birim testleri milisaniyeler içinde çalışırken, entegrasyon testleri saniyeler ve dakikalar içinde çalışır.

Beş Test Doubles Türü

Gerard Meszaros sınıflandırması, davranış ve amaç bakımından farklılık gösteren beş Test Doubles türünü içerir. Aralarındaki farkı anlamak, yetkin birim testlerin temelidir.

Dummy

Dummy, test edilen metoda iletilen ancak asla kullanılmayan bir nesnedir. Dummy yalnızca metot imzasını karşılamak için gereklidir. Kotlin'de bu genellikle null, emptyList() veya stub'lı bir nesnedir. Dummy hiçbir mantık içermemelidir — çağrılırsa test başarısız olmalıdır.

Fake

Fake, bir arayüzün basitleştirilmiş ancak çalışan bir uygulamasıdır. Mock ve Stub'un aksine, Fake gerçek iş mantığı içerir, ancak basitleştirilmiş biçimde. Klasik bir örnek, verileri bir veritabanı yerine HashMap'te saklayan InMemoryUserRepository'dir. Fake, gerçek altyapının yükü olmadan duruma bağlı mantığı test etmeniz gerektiğinde kullanılır.

TürAmaçÖrnek
DummyParametre doldurmanull, boş nesne
FakeÇalışan basitleştirilmiş uygulamaInMemoryRepository
StubSabit değer döndürmewhen(api.getUser()).thenReturn(user)
SpyDoğrulama için çağrıları kaydetmeverify(spy).save(user)
MockEtkileşimi doğrulamaverify(mock).sendEmail(email)

Stub

Stub, belirli çağrılar için önceden tanımlanmış değerler döndürür. Stub çağrılıp çağrılmadığını kontrol etmez — yalnızca veri sağlar. Mockito'da Stub, when(method).thenReturn(value) ile oluşturulur. Stub, bir bağımlılığın belirli bir değer döndürmesi gerektiğinde ancak çağrının kendisinin önemli olmadığı testler için idealdir.

Spy

Spy, sonraki doğrulama için tüm çağrıları kaydeden gerçek bir nesnenin etrafındaki bir sarmalayıcıdır. Mock'un aksine, Spy çağrıları gerçek nesneye devreder ancak gerçekleştiklerini doğrulamaya izin verir. Mockito'da Spy, spy(realObject) ile oluşturulur. Spy, gerçek bir nesne kullanmak ancak bazı çağrıları doğrulamak istediğinizde kısmi mocking için kullanışlıdır.

Mock

Mock, önceden tanımlanmış çağrı beklentilerine sahip bir nesnedir. Mock, belirli metotların belirli argümanlarla ve belirli bir sırayla çağrıldığını doğrular. Stub'un aksine Mock, veri döndürmekten ziyade davranış doğrulamasına odaklanır. Mock, mobil geliştirmede en güçlü ve en sık kullanılan Test Double türüdür.

Mock ve Stub: Temel Farklar

Mock ve Stub arasındaki fark, deneyimli geliştiriciler arasında bile sıklıkla karışıklığa neden olur. Temel fark amaçtadır: Stub durum doğrulaması (state verification) yapar, Mock davranış doğrulaması (behavior verification) yapar.

Stub şu soruyu yanıtlar: “kod doğru sonucu döndürdü mü?”. Mock şu soruyu yanıtlar: “kod doğru argümanlarla doğru metotları çağırdı mı?”. Mobil geliştirmede, Stub sonucun önemli olduğu durumlarda (ör., bir depodan veri) kullanılırken, Mock yan etkilerin önemli olduğu durumlarda (ör., e-posta gönderme, veritabanına yazma) kullanılır.

kotlin
// Stub: durum doğrulaması
every { repository.getUsers() } returns listOf(user)
val result = useCase.getUsers()
assertEquals(1, result.size)

// Mock: davranış doğrulaması
every { analytics.logEvent("purchase") } returns Unit
useCase.purchase(item)
verify { analytics.logEvent("purchase") }

Kotlin'de Test Doubles Örnekleri

MockK kullanarak Kotlin'deki beş Test Doubles türünün tümüne dair pratik örnekler — Android projeleri için en popüler mocking kütüphanesi.

Fake: InMemoryUserRepository

kotlin
class InMemoryUserRepository : UserRepository {
    private val store = mutableMapOf<String, User>()

    override fun save(user: User) {
        store[user.email] = user
    }

    override fun findByEmail(email: String): User? {
        return store[email]
    }
}

Stub + Mock: UseCase testi

kotlin
class RegisterUseCaseTest {
    private val api = mockk<AuthApi>()
    private val repo = spyk(InMemoryUserRepository())
    private val useCase = RegisterUseCase(api, repo)

    fun `register user successfully`() = runTest {
        // Stub: sabit API yanıtı döndür
        coEvery { api.register("test@test.com") } returns AuthResult.Success("token123")

        val result = useCase.execute("test@test.com")

        // Verify: kullanıcının kaydedildiğini doğrula
        verify { repo.save(any()) }
        assertTrue(result.isSuccess())
    }
}

Dummy: kullanılmayan parametre ile test

kotlin
data class Logger(val appContext: Context, val format: FormatType)

fun `test logger with dummy context`() {
    // Dummy: Context, Logger içinde kullanılmaz
    val dummyContext = mockk<Context>()
    val logger = Logger(dummyContext, FormatType.JSON)
    assertEquals(FormatType.JSON, logger.format)
}

Mobil Geliştirmede Hangi Tür Ne Zaman Kullanılır

Test Double türünün seçimi, tam olarak neyin test edildiğine bağlıdır: durum, davranış veya entegrasyon. Android ve iOS mobil geliştirmede aşağıdaki öneriler oluşturulmuştur.

ViewModel ve UseCase İçin

ViewModel test edilirken, yan etki üreten bağımlılıklar (depolar, analitik, navigasyon) için Mock kullanın ve veri döndüren bağımlılıklar (API istemcileri, ContentProvider) için Stub kullanın. Bu, ViewModel'in hem başarı hem de hata senaryolarını doğru şekilde işlediğini doğrulamaya olanak tanır.

Repository ve Veri Katmanı İçin

Repository düzeyinde, Fake (bellek içi veritabanı uygulamaları) ve Stub (sabit API yanıtları) tercih edin. Fake, SQLite kurmadan önbellek mantığını ve çevrimdışı modu test etmeye olanak tanır. Stub, çeşitli HTTP durumlarını simüle eder: 200, 404, 500, timeout.

  • İş mantığı birim testleri — tüm dış bağımlılıklar için Mock, kullanılmayan parametreler için Dummy
  • Entegrasyon testleri — Mock yerine Fake (bileşenlerin birlikte çalıştığını doğrulama)
  • UI testleri — API yanıtları için Stub (MockWebServer veya WireMock ile)
  • Önbellek testleri — veritabanı için Fake (Room/SQLite yerine bellek içi)
  • Eşzamansızlık testleri — coroutine desteği ile Mock (Flow için MockK + Turbine)

Yedek Nesneleri Kullanırken Sık Yapılan Hatalar

Test Doubles'ın yanlış kullanımı, her yeniden düzenlemede bozulan kırılgan testlerin en yaygın nedenlerinden biridir.

Aşırı Mocking: Mock'un Aşırı Kullanımı

En yaygın hata, her şeyi mocklamaktır. Bir testteki her bağımlılık Mock ile değiştirilirse, test gerçek davranışı doğrulamayı bırakır. Mock yalnızca dış bağımlılıklar için kullanılmalıdır (ağ, veritabanı, dosya sistemi, sistem hizmetleri). İç uygulama bileşenleri (Value Object, data class, basit yardımcı programlar) değiştirilmemelidir.

Eksik Belirleme: Yetersiz Belirtim

İkinci hata, beklentileri tanımlamadan Mock oluşturmaktır. Bir metot every / when olmadan çağrılırsa, Mock varsayılan bir değer döndürür (null, 0, false). Bu, Mock'un sessizce null döndürdüğü ve testin bunu doğru davranış olarak yorumladığı yanlış pozitif testlere yol açabilir.

Aşırı Doğrulama: Verify'ın Aşırı Kullanımı

Üçüncü hata, her Mock'un her çağrısını doğrulamaktır. Verify yalnızca iş mantığı açısından kritik öneme sahip çağrılar için kullanılmalıdır. Aşırı doğrulama testleri kırılgan hale getirir: üretim kodundaki çağrı sırasını değiştirmek, davranışı değiştirmeden testleri bozar.

Sıkça Sorulan Sorular

Mock ve Stub arasındaki fark nedir?

Stub veri döndürür ve durumu (ne döndürüldüğünü) doğrular, Mock ise davranışı bank (bank metotların çağrıldığını) doğrular. Stub = “X'i döndür”, Mock = “Y'nin Z argümanıyla çağrıldığını doğrula”. Gerçek testlerde, bir nesne genellikle aynı anda hem Stub hem de Mock olarak işlev görür.

Mock yerine Fake ne zaman kullanılır?

Fake, duruma bağlı mantık test edilirken (önbellekleme, çevrimdışı mod, işlemler) Mock'tan tercih edilir. Fake (bellek içi uygulama), kırılgan verify çağrıları olmadan bu senaryoları test etmeye olanak tanır. Mock, veri göndermeyi doğrulamak için daha uygundur: analitik, push, e-posta.

Android için en iyi Test Doubles kütüphanesi hangisidir?

Kotlin'deki Android projeleri için MockK önerilir. Ek yapılandırma gerektirmeden coroutine, suspend fonksiyonlar, sealed class ve extension fonksiyonları destekler. Java projeleri için Mockito standart olmaya devam etmektedir — kapsamlı dokümantasyona sahip en popüler kütüphane.

Test Doubles ile Kotlin Flow nasıl test edilir?

Kotlin Flow'yu test etmek için MockK ile birlikte Turbine kütüphanesini kullanın. Turbine, Flow emisyonlarını doğrulamayı basitleştirir: değerlerin sırasını, akış tamamlanmasını ve istisnaları doğrulayabilirsiniz. Flow için Stub flowOf(value) döndürür, Mock Flow'un toplandığını doğrular.

UI testlerinde Test Doubles kullanmak kabul edilebilir mi?

Evet, ancak API yanıtları düzeyinde, UI bileşenleri düzeyinde değil. MockWebServer (OkHttp) ve WireMock kütüphaneleri, UI testlerinde HTTP yanıtlarını simüle etmeye olanak tanır. UI bileşenlerinin kendileri (Compose, SwiftUI Views) değiştirilmemelidir — davranışları ekran görüntüsü testleri ve Espresso ile test edilir.

Özet

  • Test Doubles — beş tür yedek nesne için genel terim: Mock, Stub, Fake, Spy, Dummy
  • Mock davranışı doğrular (verify), Stub veri döndürür (thenReturn), Fake basitleştirilmiş gerçek uygulama olarak çalışır
  • Spy gerçek bir nesneyi sarar ve çağrıları kaydeder, Dummy kullanılmayan parametreleri doldurur
  • Gerard Meszaros tipolojisi, tüm modern mocking çerçevelerinde kullanılan kanonik sınıflandırmadır
  • Kotlin projeleri için MockK önerilir, Java için — Mockito, iOS için — Cuckoo veya OHHTTPStubs
  • Sık yapılan hatalar: aşırı mocking (her şeyi değiştirme), eksik belirleme (tanımsız beklentiler), aşırı doğrulama (aşırı verify)
  • Fake, durumlu mantık test edilirken Mock'tan tercih edilir — önbellekleme, çevrimdışı mod ve işlemler

Anahtar teslim bir mobil uygulama geliştireceğiz

IT Sectr, 2017'den beri girişimler ve işletmeler için iOS ve Android uygulamaları oluşturmaktadır. Size danışmanlık yapacak ve en iyi çözümü önereceğiz.

Projeyi tartış

Ayrıca okuyun