Stub: bu nədir, növləri və testdə tətbiqi

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

Stub (zastupluq, test köməkçisi) — real implementasiya əvəzinə metod çağırışlarına əvvəlcədən təyin edilmiş cavablar qaytaran test obyekti. Mobil inkişafda stublar test edilən modulu şəbəkə sorğularından, verilənlər bazasından və fayl sistemindən təcrid edərək, mühit qurulması olmadan məntiqin yoxlanılmasına imkan verir. Mock-dan fərqli olaraq, stub davranışı yoxlamır — o yalnız məlumat təqdim edir. Ətraflı — Martin Fowler-in test dublörləri haqqında məqaləsində.

Əsas məqamlar

  • Stub — məntiqsiz metod çağırışlarına verilən qiymətləri qaytaran zastupluq
  • İzolyasiya — stublar real asılılıqları söndürür: API, VB, fayllar, sensorlar
  • Mock-dan fərq — stub çağırışları yoxlamır, o yalnız cavabı əvəz edir
  • Android — MockWebServer (OkHttp) HTTP üçün stub kimi, MockK.constantAnswer Kotlin üçün
  • iOS — OCMock və Swift protokolları test implementasiyaları ilə stublar kimi

Stub nədir və digər test dublörlərindən nə fərqi var?

Stub — testdə real asılılığı əvəz edən və müəyyən çağırışlara əvvəlcədən təyin edilmiş qiymətlər qaytaran obyekt-zastupluqdur. Termin Gerard Meszaros (2007) tərəfindən „xUnit Test Patterns" kitabında təsnifata daxil edilmişdir. Stub test dublörləri — test zamanı real komponentləri əvəz edən obyektlər kateqoriyasına aiddir. Stub-un əsas məqsədi xarici sistemlərin qeyri-müəyyənliyini aradan qaldıraraq test edilən bloku proqnozlaşdırıla bilən məlumatlarla təmin etməkdir.

İş prinsipi — test icradan əvvəl stubları konfiqurasiya edir: „getUsers() metodu çağırıldıqda, bu istifadəçi siyahısını qaytar". Stub biznes məntiqini ehtiva etmir, çağırışların ardıcıllığını yoxlamır və müraciət tarixçəsini qeyd etmir. O sadəcə real komponentin yerində dayanır və ona deyilənləri qaytarır. Android testi kontekstində bu o deməkdir ki, OkHttp müştərisi real sorğunu serverə göndərmir, əvəzində stub kimi konfiqurasiya edilmiş MockWebServer-dən cavab alır.

  • Stub — məlumat qaytarır, çağırışları yoxlamır
  • Mock — məlumat qaytarır və davranışı yoxlayır (verify)
  • Fake — real məntiqlə işləyən sadələşdirilmiş implementasiya
  • Spy — real obyekti bürüyərək çağırışları qeyd edir
  • Dummy — ötürülür, lakin istifadə olunmur (null, boş obyekt)

Nə vaxt istifadə etməli — stublar UI qatının (ViewModel, Presenter) və biznes məntiqinin (UseCase, Interactor) testi üçün optimaldır, burada konkret məlumatlara reaksiyanı yoxlamaq lazımdır: siyahı boşdur, server 500 xətası qaytardı, token vaxtı keçdi. Testin müəyyən giriş vəziyyəti tələb etdiyi hər bir hal stub üçün tapşırıqdır. Hər test ssenarisi üçün öz stub konfiqurasiyası yaradılır ki, bu da testləri oxunaqlı və proqnozlaşdırıla bilən edir.

Meszaros-a görə test dublörlərinin təsnifatı

Gerard Meszaros (2007) „xUnit Test Patterns" kitabında test dublörlərinin beş növünü ayırd etmişdir: dummy, stub, spy, mock, fake. Hər növ öz tapşırığını həll edir. Dummy — ötürülür, lakin istifadə olunmur. Stub — məlumat qaytarır. Spy — çağırışları qeyd edir. Mock — davranışı yoxlayır. Fake — sadələşdirilmiş məntiqi ehtiva edir. Bu təsnifatı anlamaq proqramçıya hər test ssenarisi üçün düzgün aləti seçməyə kömək edir.

Mobil tətbiqlərin testində stublar harada istifadə olunur

Şəbəkə sorğuları üçün stublar

Şəbəkə sorğuları — stubların ən çox istifadə edildiyi ssenari. Tətbiq API-ə HTTP çağırışları edir və testdə müxtəlif cavablara reaksiyanı yoxlamaq lazımdır: uğurlu JSON, 401 xətası (icazəsiz), vaxt aşımı, boş massiv. Android-də MockWebServer (OkHttp) və iOS-də URLProtocol stublar rolunu oynayaraq real serverə qoşulmadan əvvəlcədən təyin edilmiş HTTP cavabları qaytarır. Bu testləri saniyələrdən millisaniyələrə sürətləndirir.

Verilənlər bazası — Room (Android) və CoreData (iOS) in-memory variantlarına malikdir, lakin onların qurulması yenə də vaxt tələb edir. Stub repository əvəzinə əvvəlcədən hazırlanmış Entity siyahılarını qaytarır, VB-yə toxunmadan. Bu xüsusilə ViewModel-in testi üçün effektivdir, burada çeşidləmə, filtrləmə və ya məlumat transformasiyasını yoxlamaq lazımdır. Test məlumatların həcmindən asılı olmayaraq millisaniyələr ərzində icra olunur.

Sistem xidmətləri — LocationManager, SensorManager, SharedPreferences real cihaz və ya emulator tələb edir. LocationProvider üçün stub verilmiş koordinatları, SensorManager üçün — akselerometrin sabit qiymətlərini qaytarır. iOS-də analoq — CLLocationManager test deleqat implementasiyası ilə. Stublar olmadan belə testlər müəyyən şərtləri olan fiziki cihaz tələb edir.

Fayl sistemi və keş — şəkillərin yüklənməsi, cavabların keşlənməsi, konfiqurasiya faylları ilə iş — bütün bu əməliyyatlar diskin vəziyyətindən asılıdır. FileManager və ya ImageCache üçün stub real faylları oxumadan uğur/xəta qaytarır. Bu, müxtəlif tərtibatçı maşınlarında yolların və ya icazələrin uyğunsuzluğu səbəbindən testlərin yalançı çökmələrini aradan qaldırır.

Stub vs Mock vs Fake: əsas fərqlər

Məsuliyyətlərin bölünməsi — üç növ test dublörü müxtəlif tapşırıqları həll edir. Stub: „mənə məlumat ver". Mock: „yoxla ki, məni çağırdılar". Fake: „mən real kimi işləyirəm, sadəcə daha sadə". Fərq testlərin oxunaqlılığı üçün kritik əhəmiyyət daşıyır: əgər test stub lazım olan yerdə mock istifadə edirsə, o, test edilən ssenari ilə əlaqəsi olmayan verify çağırışları ilə yüklənir.

XüsusiyyətStubMockFake
MəqsədMəlumat təmin etməkQarşılıqlı əlaqəni yoxlamaqSadələşdirilmiş implementasiya
MəntiqYoxYoxVar (ancaq sadələşdirilmiş)
DoğrulamaYoxBəli (verify)Dolayı (vəziyyət vasitəsilə)
ÇeviklikAşağı — sərt cavablarOrtaYüksək — məntiq uyğunlaşır
SürətMaksimalYüksəkOrta
NümunəMockWebServer JSON qaytarırMockito.verify(repository).save()HashMap ilə InMemoryRepository

Praktik qayda — əgər test test edilən komponentin hansı məlumatları aldığını yoxlayırsa — stub istifadə edin. Əgər test komponentin asılılıq metodunu düzgün arqumentlərlə çağırdığını yoxlayırsa — mock istifadə edin. Əgər sadəcə VB-ni hash cədvəli ilə əvəz etmək istəyirsinizsə — bu fake-dir. Bir testdə növləri qarışdırmaq onu kövrək edir: implementasiya dəyişəndə həm stub, həm də verify məntiqini yenidən yazmalı olacaqsınız.

Antipattern: verify ilə Stub

Verify ilə Stub — proqramçı stubları konfiqurasiya edib sonra verify(stub).method() əlavə etdikdə yayılmış səhv. Stub tərifinə görə doğrulanmamalıdır — doğrulama üçün mock var. Əgər metodun konkret arqumentlərlə çağırıldığını yoxlamaq lazımdırsa, Mockito.stub() əvəzinə Mockito.mock() istifadə edin. Bu bölgü testin məqsədini digər proqramçılar üçün aydın saxlayır.

Android-də MockWebServer və MockK ilə stubların reallaşdırılması

MockWebServer — Android və JVM-də HTTP stubları yaratmaq üçün OkHttp kitabxanası. O, müəyyən portda yerli HTTP serveri qaldırır, OkHttp müştərisinin sorğularını ələ keçirir və əvvəlcədən təyin edilmiş cavablar qaytarır. Quraşdırma üç sətir çəkir: server yarat, cavabı növbəyə qoy (enqueue), işə sal. Test paginasiya və ya təkrar cəhdlər üçün ardıcıl olaraq bir neçə cavabı növbəyə qoya bilər.

kotlin
class UserRepositoryTest {

    private val server = MockWebServer()

    fun setup() {
        server.start(8080)
        val client = OkHttpClient.Builder()
            .readTimeout(1, TimeUnit.SECONDS)
            .build()
    }

    fun test_user_list_success() {
        val json = "[{\"id\":1,\"name\":\"Alice\"}]"
        server.enqueue(MockResponse()
            .setBody(json)
            .setResponseCode(200)
        )
        val result = repository.getUsers()
        assertEquals(1, result.size)
    }

    fun teardown() {
        server.shutdown()
    }
}

MockK — Kotlin üçün Mockito-ya alternativ, korutinlər, genişləndirmə funksiyaları və sealed siniflər üçün first-class dəstək ilə. MockK-da stublar coEvery (suspend funksiyaları üçün) və every (adî funksiyalar üçün) vasitəsilə yaradılır. MockWebServer-dən fərqli olaraq, MockK bütün HTTP qatını deyil, ayrı-ayrı asılılıq metodlarını əvəz edir. Bu, asılılıqları repository abstraksiyaları olan UseCase və ya Interactor unit testləri üçün əlverişlidir.

kotlin
interface UserRepository {
    suspend fun getUsers(): List<User>
}

class GetUsersUseCaseTest {

    private val repo = mockk<UserRepository>()

    private val useCase = GetUsersUseCase(repo)

    fun test_empty_list() = runTest {
        coEvery { repo.getUsers() } returns emptyList()

        val result = useCase.invoke()

        assertTrue(result.isEmpty())
        coVerify(exactly = 1) { repo.getUsers() }
    }
}

Best practice — inteqrasiya testləri üçün MockWebServer istifadə edin (real HTTP-ni ələ keçirir), unit testləri üçün — MockK (interfeysləri əvəz edir). Test etmədiyiniz şeyi əvəz etməyin: əgər test Repository-ni yoxlayırsa, onun daxilində OkHttp müştərisini əvəz etməyin — HTTP səviyyəsində real MockWebServer istifadə edin. Bu qayda testləri aktual saxlayır və refaktoring zamanı kövrəkliyi azaldır.

iOS-də OCMock və protokollarla stubların reallaşdırılması

Swift protokolları stublar kimi — iOS-native yanaşmada stub asılılıq protokoluna uyğun test strukturunun yerləşdirilməsi ilə həyata keçirilir. Real NetworkService əvəzinə test StubNetworkService alır ki, o da sabit məlumatlar qaytarır. Swift statik tipli dildir, buna görə stub real xidmətlə eyni protokola uyğun olmalıdır. Kompilyator stub-un bütün tələb olunan metodları implementasiya etdiyinə zəmanət verir.

swift
protocol NetworkServiceProtocol {
    func fetchUsers() async throws -> [User]
}

struct StubNetworkService: NetworkServiceProtocol {
    let result: Result<[User], Error>

    func fetchUsers() async throws -> [User] {
        try result.get()
    }
}

final class UsersViewModelTests: XCTestCase {
    func test_success_state() async {
        let stub = StubNetworkService(
            result: .success([User(name: "Alice")])
        )
        let vm = UsersViewModel(service: stub)
        await vm.load()
        XCTAssertEqual(vm.users.count, 1)
    }
}

Objective-C üçün OCMock — legacy iOS layihələrində stublar və moklar yaratmaq üçün kitabxana. OCMock arqumentlər və qaytarılan dəyərlərlə stub metodlarını dəstəkləyir. Swift-də müasir layihələr əl ilə stublarla protokol əsaslı yanaşmaya üstünlük verir — bu, hər bir metod üzərində nəzarət verir və xarici asılılıqlar tələb etmir. OCMock bütün asılılıqların protokollaşdırılmasının iqtisadi cəhətdən məqsədəuyğun olmadığı layihələr üçün seçim olaraq qalır.

HTTP stubları üçün URLProtocol — URLProtocol alt sinfi vasitəsilə şəbəkə sorğularını ələ keçirmək üçün iOS sistem mexanizmi. Test URLSession-i ələ keçirən və stub cavabları qaytaran fərdi URLProtocol qeydiyyatdan keçirir. Əl ilə stublardan üstünlüyü: tətbiqin arxitekturasını dəyişmək lazım deyil — URLSession real qalır, lakin məlumatlar protokol səviyyəsində əvəz olunur. Çatışmazlıq: aşkar stub xidmətindən daha çətin debug edilir.

Tez-tez verilən suallar

Stub Mock-dan nə ilə fərqlənir?

Stub əvvəlcədən təyin edilmiş məlumatları qaytarır və çağırış faktını yoxlamır. Mock əlavə olaraq metodun düzgün arqumentlərlə çağırıldığını yoxlayır (verify). Stub „nə qaytarmalı" sualına, Mock „çağırış oldu mu" sualına cavab verir. Vəziyyəti yoxlamaq üçün stub, qarşılıqlı əlaqəni yoxlamaq üçün mock istifadə edin.

Nə vaxt Fake, nə vaxt Stub istifadə etməli?

Fake testin işlək (sadələşdirilmiş olsa da) implementasiya tələb etdiyi hallarda lazımdır — məsələn, Room əvəzinə in-memory verilənlər bazası. Stub əvvəlcədən təyin edilmiş məlumatlarla tək ssenarilər üçün uyğundur. Eyni stubları 10 testdə təkrar edirsinizsə — çox güman ki, Fake lazımdır. Fake dublikasiyanı azaldır, çünki məntiq bir sinifdə yaşayır.

Statik metodları əvəz etmək (stublamaq) olarmı?

Android-də — MockK Kotlin obyektləri (object) üçün mockkObject()-i, o cümlədən Java siniflərinin statik metodlarını mockkStatic() vasitəsilə dəstəkləyir. iOS-də — Swift-in statik metodları birbaşa stublanmır; static çağırışını protokolun instansiya metodu ilə əvəz etmək üçün protokollar və DI istifadə edin. Statik stublar texniki borcdur, yeni kodda onlardan qaçınmaq lazımdır.

Android-də şəbəkə sorğularını necə stublamaq olar?

MockWebServer (OkHttp) istifadə edin — o, cavabları növbəyə qoyan (enqueue) lokal HTTP serveri kimi işləyir. Retrofit üçün əsas URL-i localhost:8080-ə dəyişmək kifayətdir. Ktor üçün MockEngine istifadə edin — HttpStatement-i əvəz etmək üçün daxili mexanizm. Hər iki yanaşma real internet olmadan işləyir və status kodu, cavab mətni və başlıqlar üzərində tam nəzarət verir.

Stub vs Spy — fərq nədir?

Spy real obyekti bürüyür və çağırışları qeyd edir, Stub isə obyekti tamamilə sabit cavablarla əvəz edir. Spy real implementasiyadan qismən istifadə etməyə imkan verir (qalan metodlar olduğu kimi işləyir), stub isə vermir. Əgər metodun çağırıldığını yoxlamaq lazımdır, lakin məntiqin bir hissəsi icra olunmalıdırsa — stub yox, spy istifadə edin.

Nəticə

  • Stub — test zamanı metod çağırışlarına əvvəlcədən təyin edilmiş cavablar qaytaran obyekt-zastupluq
  • Asılılıqların izolyasiyası — stublar şəbəkə sorğularını, VB-ni, sistem xidmətlərini və fayl sistemini əvəz edir
  • Mock-dan fərq — stub çağırışları yoxlamır, o yalnız davranışı yoxlamadan məlumat qaytarır
  • Android alətləri — HTTP üçün MockWebServer, korutin dəstəyi ilə Kotlin interfeysləri üçün MockK
  • iOS alətləri — Swift-də protokol əsaslı stublar, HTTP üçün URLProtocol, Objective-C üçün OCMock
  • Rolları qarışdırmayın — stuba verify əlavə etməyin, çağırışların yoxlanması üçün mock istifadə edin
  • Stub + MockWebServer — real server olmadan inteqrasiya testləri üçün standart yanaşma

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