Test Doubles — bu nədir, növləri və tətbiqi

Müəllif: IT Sectr Dərc olunub: 2026-04-10 Oxuma vaxtı: 9 dəq

Test Doubles — bunlar real asılılıqların əvəzinə vahid testlərdə istifadə olunan əvəzedici obyektlərdir. Termin Gerard Meszaros tərəfindən „­xUnit Test Patterns“ (2007) kitabında Mock, Stub, Fake, Spy və Dummy üçün ümumiləşdirici anlayış kimi təqdim edilmişdir. Martin Fowler (2024)-ə görə, Test Doubles test edilən komponenti onun mühitindən təcrid etməyə imkan verir, testləri deterministik, sürətli və xarici xidmətlərdən asılı olmayan edir.

Başlıca

  • Test Doubles — testdə bütün əvəzedici obyekt növləri üçün ümumi termin
  • Mock qarşılıqlı əlaqəni yoxlayır: hansı metodların hansı arqumentlərlə çağırıldığını
  • Stub çağırışları yoxlamadan əvvəlcədən müəyyən edilmiş dəyərləri qaytarır
  • Fake — sadələşdirilmiş işləyən tətbiq (məsələn, yaddaşdaxili verilənlər bazası)
  • Spy sonrakı yoxlama üçün çağırışları qeyd edir, Dummy parametrləri doldurur

Test Doubles nədir?

Test Doubles — bu avtomobil sənayesindən (kaskadyor, aktyorlar üçün „dubl“) proqram təminatının hazırlanmasına köçürülmüş termindir. Kaskadyor aktyoru təhlükəli səhnədə əvəz etdiyi kimi, Test Double test ssenarisində real komponenti əvəz edir. Bu, real asılılıq əlçatmaz, yavaş, qeyri-deterministik və ya yan təsirlərə malik olduqda zəruridir.

Test Double anlayışı beş konkret növü əhatə edir, hər biri öz vəzifəsini həll edir. Meszaros tipologiyası kanonikdir və bütün müasir test təlimatlarında istifadə olunur. Növlər arasındakı fərq nəzarət və yoxlama dərəcəsindədir: sadə parametr doldurmadan (Dummy) tutmuş çağırış ardıcıllığının tam yoxlanmasına qədər (Mock).

Test Doubles nəyə lazımdır

Test Doubles-in əsas məqsədi test edilən modulun təcrid edilməsidir. Mobil proqramlaşdırmada real asılılıqlar API serverləri, verilənlər bazaları, fayl sistemi, cihaz sensorları, sistem xidmətləridir (LocationManager, Camera, Bluetooth). Bu komponentlərin birbaşa istifadəsi testləri yavaş, kövrək və mühitdən asılı edir. Google Testing Blog (2023) məlumatlarına görə, yaxşı təcrid edilmiş vahid testlər millisaniyələrdə, inteqrasiya testləri isə saniyə və dəqiqələrdə yerinə yetirilir.

Beş növ Test Doubles

Gerard Meszaros təsnifatı davranış və istifadə məqsədinə görə fərqlənən beş növ Test Doubles-ı əhatə edir. Onlar arasındakı fərqi başa düşmək düzgün vahid test etmənin əsasıdır.

Dummy

Dummy — bu test edilən metoda ötürülən, lakin heç vaxt istifadə olunmayan obyektdir. Dummy yalnız metodun imzasını təmin etmək üçün lazımdır. Kotlin-də bu çox vaxt null, emptyList() və ya əvəzediciləri olan obyektdir. Dummy heç bir məntiq ehtiva etməməlidir — əgər çağırılarsa, test uğsuz olmalıdır.

Fake

Fake — bu interfeysin sadələşdirilmiş, lakin işləyən tətbiqidir. Mock və Stub-dan fərqli olaraq, Fake real biznes məntiqini ehtiva edir, lakin sadələşdirilmiş formada. Klassik nümunə — verilənləri verilənlər bazası əvəzinə HashMap-də saxlayan InMemoryUserRepository. Fake, vəziyyətdən asılı məntiqi real infrastrukturun yükü olmadan test etmək lazım olduqda istifadə olunur.

TipTəyinatNümunə
DummyParametri doldurmaqnull, boş obyekt
Fakeİşləyən sadələşdirilmiş tətbiqInMemoryRepository
StubSabit dəyəri qaytarmaqwhen(api.getUser()).thenReturn(user)
SpyYoxlama üçün çağırışları qeyd etməkverify(spy).save(user)
MockQarşılıqlı əlaqəni yoxlamaqverify(mock).sendEmail(email)

Stub

Stub müəyyən çağırışlar üçün əvvəlcədən müəyyən edilmiş dəyərləri qaytarır. Stub çağırılıb-çağırılmadığını yoxlamır — sadəcə məlumat təqdim edir. Mockito-da Stub when(method).thenReturn(value) vasitəsilə yaradılır. Stub, asılılığın konkret dəyər qaytarması lazım olduqda, lakin çağırış faktının önəmli olmadığı halda test etmək üçün idealdır.

Spy

Spy — bu real obyektin ətrafında sonrakı yoxlama üçün bütün çağırışları qeyd eden sarğıcıdır. Mock-dan fərqli olaraq, Spy çağırışları real obyektə ötürür, lakin onların baş verdiyini yoxlamağa imkan verir. Mockito-da Spy spy(realObject) vasitəsilə yaradılır. Spy, real obyektdən istifadə etmək istəyən, lakin bəzi çağırışları yoxlamaq istəyən hallarda qismən mocking üçün faydalıdır.

Mock

Mock — bu əvvəlcədən müəyyən edilmiş çağırış gözləntiləri olan obyektdir. Mock müəyyən metodların müəyyən arqumentlərlə və müəyyən ardıcıllıqla çağırılıb-çağırılmadığını yoxlayır. Stub-dan fərqli olaraq, Mock məlumat qaytarmağa deyil, davranışın yoxlanmasına diqqət yetirir. Mock mobil proqramlaşdırmada ən güclü və ən çox istifadə olunan Test Double növüdür.

Mock və Stub: əsas fərqlər

MockStub arasındakı fərq hətta təcrübəli proqramçılar arasında da çox vaxt qarışıqlığa səbəb olur. Əsas fərq məqsəddədir: Stub vəziyyəti yoxlayır (state verification), Mock davranışı yoxlayır (behavior verification).

Stub suala cavab verir: „kod düzgün nəticə qaytardımı?“. Mock suala cavab verir: „kod düzgün metodları düzgün arqumentlərlə çağırdımı?“. Mobil proqramlaşdırmada Stub nəticə vacib olduqda (məsələn, repozitoridən məlumatlar), Mock isə yan təsirlər vacib olduqda (məsələn, e-poçt göndərmək, verilənlər bazasına yazmaq) istifadə olunur.

kotlin
// Stub: vəziyyətin yoxlanılması
every { repository.getUsers() } returns listOf(user)
val result = useCase.getUsers()
assertEquals(1, result.size)

// Mock: davranışın yoxlanılması
every { analytics.logEvent("purchase") } returns Unit
useCase.purchase(item)
verify { analytics.logEvent("purchase") }

Kotlin-də Test Doubles nümunələri

Android layihələri üçün ən məşhur mocking kitabxanası olan MockK istifadə edərək Kotlin-də bütün beş növ Test Doubles-un praktik nümunələri.

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 cavabını qaytarırıq
        coEvery { api.register("test@test.com") } returns AuthResult.Success("token123")

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

        // Verify: istifadəçinin yadda saxlanıldığını yoxlayırıq
        verify { repo.save(any()) }
        assertTrue(result.isSuccess())
    }
}

Dummy: istifadə olunmayan parametrlə test

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

fun `test logger with dummy context`() {
    // Dummy: Context Logger daxilində istifadə olunmur
    val dummyContext = mockk<Context>()
    val logger = Logger(dummyContext, FormatType.JSON)
    assertEquals(FormatType.JSON, logger.format)
}

Mobil proqramlaşdırmada hansı tipi nə vaxt tətbiq etməli

Test Double növünün seçimi dəqiq nəyin test edildiyindən asılıdır: vəziyyət, davranış və ya inteqrasiya. Android və iOS üzrə mobil proqramlaşdırmada aşağıdakı tövsiyələr formalaşmışdır.

ViewModel və UseCase üçün

ViewModel-in test edilməsində yan təsirlər yaradan asılılıqlar (repozitorilər, analitika, naviqasiya) üçün Mock, məlumat qaytaran asılılıqlar (API müştəriləri, ContentProvider) üçün isə Stub istifadə edin. Bu, ViewModel-in həm uğurlu, həm də səhv ssenarilərini düzgün idarə etdiyini yoxlamağa imkan verir.

Repository və Məlumat Təbəqəsi üçün

Repository səviyyəsində Fake (yaddaşdaxili verilənlər bazası tətbiqləri) və Stub (sabit API cavabları) üstünlük təşkil edir. Fake SQLite konfiqurasiyası olmadan keşləmə və oflayn rejim məntiqini yoxlamağa imkan verir. Stub müxtəlif HTTP statuslarını simulyasiya edir: 200, 404, 500, timeout.

  • Biznes məntiqinin vahid testləri — bütün xarici asılılıqlar üçün Mock, istifadə olunmayan parametrlər üçün Dummy
  • İnteqrasiya testləri — Mock əvəzinə Fake (komponentlərin birlikdə işlədiyini yoxlayırıq)
  • UI testləri — API cavabları üçün Stub (MockWebServer və ya WireMock vasitəsilə)
  • Keşləmə testləri — verilənlər bazası üçün Fake (Room/SQLite əvəzinə yaddaşdaxili)
  • Asinxronluq testləri — korutin dəstəyi ilə Mock (Flow üçün MockK + Turbine)

Əvəzedicilərdən istifadədə tipik səhvlər

Test Doubles-in düzgün istifadə edilməməsi hər refaktorinqdə pozulan kövrək testlərin ən çox yayılmış səbəblərindən biridir.

Over-mocking: həddən artıq Mock istifadəsi

Ən çox yayılmış səhv — hər şeyin mock edilməsidir. Əgər testdə hər asılılıq Mock ilə əvəz edilirsə, test real davranışı yoxlamağı dayandırır. Mock yalnız xarici asılılıqlar üçün olmalıdır (şəbəkə, verilənlər bazası, fayl sistemi, sistem xidmətləri). Tətbiqin daxili komponentləri (Value Object, data class, sadə köməkçi alətlər) əvəz edilməməlidir.

Under-specification: qeyri-kafi spesifikasiya

İkinci səhv — gözləntilər müəyyən edilmədən Mock yaratmaq. Əgər metod every / when olmadan çağırılırsa, Mock standart dəyər qaytarır (null, 0, false). Bu, Mock səssizcə null qaytardıqda və test bunu düzgün davranış kimi şərh etdikdə yalançı müsbət testlərə səbəb ola bilər.

Over-verification: həddən artıq yoxlama

Üçüncü səhv — hər Mock-un hər çağırışının yoxlanmasıdır. Verify yalnız biznes məntiqi baxımından kritik olan çağırışlar üçün istifadə edilməlidir. Həddən artıq yoxlama testləri kövrək edir: istehsal kodunda çağırış ardıcıllığının dəyişməsi davranışı dəyişmədən testləri pozur.

Tez-tez verilən suallar

Mock və Stub arasındakı fərq nədir?

Stub məlumatları qaytarır və vəziyyəti yoxlayır (nə qaytarıldı), Mock isə davranışı yoxlayır (hansı metodların çağırıldığı). Stub = „X-i qaytar“, Mock = „Y-nin Z arqumenti ilə çağırıldığını yoxla“. Real testlərdə bir obyekt çox vaxt həm Stub, həm də Mock rolunu oynayır.

Nə vaxt Mock əvəzinə Fake istifadə etməli?

Fake Mock-dan üstün tutulur, nə zaman ki vəziyyətdən asılı məntiq test edilir: keşləmə, oflayn rejim, tranzaksiyalar. Fake (yaddaşdaxili tətbiq) kövrək verify çağırışları olmadan bu ssenariləri yoxlamağa imkan verir. Mock məlumat göndərilməsinin yoxlanması üçün daha uyğundur: analitika, push bildirişləri, e-poçt.

Android üçün hansı Test Doubles kitabxanası daha yaxşıdır?

Kotlin-də Android layihələri üçün MockK tövsiyə olunur. O, korutinləri, suspend-funksiyaları, sealed class və extension-funksiyaları əlavə konfiqurasiya olmadan dəstəkləyir. Java layihələri üçün standart hələ də Mockito olaraq qalır — geniş sənədləşdirməyə malik ən məşhur kitabxana.

Kotlin Flow-u Test Doubles ilə necə test etməli?

Kotlin Flow-un test edilməsi üçün MockK ilə birlikdə Turbine kitabxanasından istifadə edin. Turbine Flow emissiyasının yoxlanmasını sadələşdirir: dəyərlərin sırasını, axının tamamlanmasını və istisnaları yoxlamaq olar. Flow üçün Stub flowOf(value) qaytarır, Mock Flow-un yığıldığını yoxlayır.

UI testlərində Test Doubles istifadə etmək olarmı?

Bəli, lakin API cavabları səviyyəsində, UI komponentləri yox. MockWebServer (OkHttp) və WireMock kitabxanaları UI testlərində HTTP cavablarını əvəz etməyə imkan verir. UI komponentlərinin özləri (Compose, SwiftUI Views) əvəz edilməməlidir — onların davranışı screenshot testləri və Espresso vasitəsilə test edilir.

Nəticələr

  • Test Doubles — beş növ əvəzedici obyekt üçün ümumi termin: Mock, Stub, Fake, Spy, Dummy
  • Mock davranışı yoxlayır (verify), Stub məlumatları qaytarır (thenReturn), Fake — sadələşdirilmiş real tətbiq kimi işləyir
  • Spy real obyekti sarır və çağırışları qeyd edir, Dummy istifadə olunmayan parametrləri doldurur
  • Gerard Meszaros tipologiyası — bütün müasir mocking çərçivələrində istifadə olunan kanonik təsnifat
  • Kotlin layihələri üçün MockK, Java üçün Mockito, iOS üçün Cuckoo və ya OHHTTPStubs tövsiyə olunur
  • Tipik səhvlər: over-mocking (hər şeyin əvəz edilməsi), under-specification (müəyyən edilməmiş gözləntilər), over-verification (həddən artıq yoxlama)
  • Fake vəziyyətlə məntiqin test edilməsində Mock-dan üstün tutulur — keşləmə, oflayn rejim və tranzaksiyalar

Açar təslim mobil tətbiq hazırlayacağıq

IT Sectr 2017-ci ildən startaplar və bizneslər üçün iOS və Android tətbiqləri yaradır. Sizə məsləhət verəcəyik və ən yaxşı həlli təklif edəcəyik.

Layihəni müzakirə et

Həm də oxuyun