Test Doubles — bu haqiqiy bog‘liqliklar o‘rniga birlik testlarda ishlatiladigan o‘rnini bosuvchi ob'ektlardir. Bu atama Gerard Meszaros tomonidan „xUnit Test Patterns“ (2007) kitobida Mock, Stub, Fake, Spy va Dummy uchun umumlashtiruvchi tushuncha sifatida kiritilgan. Martin Fowler (2024) ma’lumotlariga ko‘ra, Test Doubles sinovdan o‘tayotgan komponentni uning muhitidan ajratishga imkon beradi, testlarni deterministik, tez va tashqi xizmatlardan mustaqil qiladi.
Asosiy
Test Doubles — bu avtomobil sanoatidan (kaskadyor, aktyorlar uchun „dubl“) dasturiy ta’minot ishlab chiqishga ko‘chirilgan atamadir. Kaskadyor aktyorni xavfli sahnada almashtirganidek, Test Double test ssenariysida haqiqiy komponentni almashtiradi. Bu haqiqiy bog‘liqlik mavjud bo‘lmaganda, sekin, noaniq yoki yon ta’sirga ega bo‘lganda zarurdir.
Test Double tushunchasi besh aniq turni o‘z ichiga oladi, ularning har biri o‘z vazifasini hal qiladi. Meszaros tipologiyasi kanonikdir va barcha zamonaviy test qo‘llanmalarida ishlatiladi. Turlar orasidagi farq nazorat va tekshirish darajasida: oddiy parametr to‘ldirishdan (Dummy) to chaqiriqlar ketma-ketligini to‘liq tekshirishgacha (Mock).
Test Doubles ning asosiy maqsadi sinovdan o‘tayotgan modulni ajratishdir. Mobil ishlanmada haqiqiy bog‘liqliklar API serverlari, ma’lumotlar bazalari, fayl tizimi, qurilma sensorlari, tizim xizmatlari (LocationManager, Camera, Bluetooth). Bu komponentlardan to‘g‘ridan-to‘g‘ri foydalanish testlarni sekin, mo‘rt va muhitga bog‘liq qiladi. Google Testing Blog (2023) ma’lumotlariga ko‘ra, yaxshi ajratilgan birlik testlar millisekundlarda, integrasion testlar esa soniya va daqiqalarda bajariladi.
Gerard Meszaros tasnifi xulq-atvor va foydalanish maqsadiga ko‘ra farqlanadigan besh turdagi Test Doubles ni o‘z ichiga oladi. Ularning orasidagi farqni tushunish to‘g‘ri birlik testlashning asosidir.
Dummy — bu sinovdan o‘tayotgan metodga uzatiladigan, lekin hech qachon ishlatilmaydigan ob'ektdir. Dummy faqat metod imzosini qondirish uchun kerak. Kotlin da bu ko‘pincha null, emptyList() yoki to‘ldiruvchilari bo‘lgan ob'ektdir. Dummy hech qanday mantiqni o‘z ichiga olmasligi kerak — agar chaqirilsa, test muvaffaqiyatsiz bo‘lishi kerak.
Fake — bu interfeysning soddalashtirilgan, ammo ishlaydigan tatbiqidir. Mock va Stub dan farqli o‘laroq, Fake haqiqiy biznes mantiqini o‘z ichiga oladi, lekin soddalashtirilgan shaklda. Klassik misol — ma’lumotlarni ma’lumotlar bazasi o‘rniga HashMap da saqlaydigan InMemoryUserRepository. Fake, holatga bog‘liq mantiqni haqiqiy infratuzilma yukisiz test qilish kerak bo‘lganda ishlatiladi.
| Tur | Vazifa | Misol |
|---|---|---|
| Dummy | Parametrni to‘ldirish | null, bo‘sh ob'ekt |
| Fake | Ishlaydigan soddalashtirilgan tatbiq | InMemoryRepository |
| Stub | Ruxsat etilgan qiymatni qaytarish | when(api.getUser()).thenReturn(user) |
| Spy | Tekshirish uchun chaqiriqlarni yozib olish | verify(spy).save(user) |
| Mock | O‘zaro ta’sirni tekshirish | verify(mock).sendEmail(email) |
Stub ma’lum chaqiriqlar uchun oldindan belgilangan qiymatlarni qaytaradi. Stub chaqirilganligini tekshirmaydi — shunchaki ma’lumot taqdim etadi. Mockito da Stub when(method).thenReturn(value) orqali yaratiladi. Stub, bog‘liqlik aniq qiymat qaytarishi kerak bo‘lganda, lekin chaqiruv faktining o‘zi muhim bo‘lmaganda test qilish uchun idealdir.
Spy — bu haqiqiy ob'ekt atrofidagi o‘rovchi bo‘lib, keyingi tekshirish uchun barcha chaqiriqlarni yozib oladi. Mock dan farqli o‘laroq, Spy chaqiriqlarni haqiqiy ob'ektga yo‘naltiradi, lekin ularning sodir bo‘lganligini tekshirishga imkon beradi. Mockito da Spy spy(realObject) orqali yaratiladi. Spy, haqiqiy ob'ektdan foydalanmoqchi bo‘lgan, lekin ba’zi chaqiriqlarni tekshirmoqchi bo‘lgan hollarda qisman mocking uchun foydalidir.
Mock — bu oldindan belgilangan chaqiruv kutishlari bo‘lgan ob'ektdir. Mock ma’lum metodlarning ma’lum argumentlar bilan va ma’lum ketma-ketlikda chaqirilganligini tekshiradi. Stub dan farqli o‘laroq, Mock ma’lumot qaytarishga emas, xulq-atvorni tekshirishga e’tibor qaratadi. Mock mobil ishlanmada eng kuchli va eng ko‘p ishlatiladigan Test Double turidir.
Mock va Stub orasidagi farq hatto tajribali dasturchilar orasida ham chalkashlikka sabab bo‘ladi. Asosiy farq maqsadda: Stub holatni tekshiradi (state verification), Mock xulq-atvorni tekshiradi (behavior verification).
Stub savolga javob beradi: „kod to‘g‘ri natijani qaytardimi?“. Mock savolga javob beradi: „kod to‘g‘ri metodlarni to‘g‘ri argumentlar bilan chaqirdimi?“. Mobil ishlanmada, Stub natija muhim bo‘lganda (masalan, repozitoriy ma’lumotlari), Mock esa yon ta’sirlar muhim bo‘lganda (masalan, elektron pochta jo‘natish, ma’lumotlar bazasiga yozish) ishlatiladi.
// Stub: holatni tekshirish
every { repository.getUsers() } returns listOf(user)
val result = useCase.getUsers()
assertEquals(1, result.size)
// Mock: xulq-atvorni tekshirish
every { analytics.logEvent("purchase") } returns Unit
useCase.purchase(item)
verify { analytics.logEvent("purchase") }
Android loyihalari uchun eng mashhur mocking kutubxonasi bo‘lgan MockK yordamida Kotlin da barcha besh turdagi Test Doubles ning amaliy misollari.
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]
}
}
class RegisterUseCaseTest {
private val api = mockk<AuthApi>()
private val repo = spyk(InMemoryUserRepository())
private val useCase = RegisterUseCase(api, repo)
fun `register user successfully`() = runTest {
// Stub: sobit API javobini qaytaramiz
coEvery { api.register("test@test.com") } returns AuthResult.Success("token123")
val result = useCase.execute("test@test.com")
// Verify: foydalanuvchining saqlanganligini tekshiramiz
verify { repo.save(any()) }
assertTrue(result.isSuccess())
}
}
data class Logger(val appContext: Context, val format: FormatType)
fun `test logger with dummy context`() {
// Dummy: Context Logger ichida ishlatilmaydi
val dummyContext = mockk<Context>()
val logger = Logger(dummyContext, FormatType.JSON)
assertEquals(FormatType.JSON, logger.format)
}
Test Double turini tanlash aynan nima sinovdan o‘tayotganiga bog‘liq: holat, xulq-atvor yoki integrasiya. Android va iOS da mobil ishlanmada quyidagi tavsiyalar shakllangan.
ViewModel ni test qilishda yon ta’sir ko‘rsatadigan bog‘liqliklar (repozitoriyalar, analitika, navigatsiya) uchun Mock, ma’lumot qaytaradigan bog‘liqliklar (API mijozlari, ContentProvider) uchun Stub dan foydalaning. Bu ViewModel ning muvaffaqiyatli va xato ssenariylarini to‘g‘ri boshqarishini tekshirishga imkon beradi.
Repository darajasida Fake (xotira ichidagi ma’lumotlar bazasi tatbiqlari) va Stub (sobit API javoblari) afzal. Fake SQLite sozlamasisiz keshlash va oflayn rejim mantiqini tekshirishga imkon beradi. Stub turli HTTP statuslarini simulyatsiya qiladi: 200, 404, 500, timeout.
Test Doubles dan noto‘g‘ri foydalanish — har bir qayta qurishda buziladigan mo‘rt testlarning eng keng tarqalgan sabablaridan biridir.
Eng keng tarqalgan xato — hamma narsani mock qilish. Agar testdagi har bir bog‘liqlik Mock bilan almashtirilsa, test haqiqiy xulq-atvorni tekshirishni to‘xtatadi. Mock faqat tashqi bog‘liqliklar uchun bo‘lishi kerak (tarmoq, ma’lumotlar bazasi, fayl tizimi, tizim xizmatlari). Ilovaning ichki komponentlari (Value Object, data class, oddiy yordamchi vositalar) almashtirilmasligi kerak.
Ikkinchi xato — kutishlarni aniqlamasdan Mock yaratish. Agar metod every / when siz chaqirilsa, Mock standart qiymat qaytaradi (null, 0, false). Bu, Mock jimgina null qaytarganda va test buni to‘g‘ri xatti-harakat deb talqin qilganda, noto‘g‘ri musbat testlarga olib kelishi mumkin.
Uchinchi xato — har bir Mock ning har bir chaqiruvini tekshirish. Verify faqat biznes mantiqi nuqtai nazaridan muhim bo‘lgan chaqiriqlar uchun ishlatilishi kerak. Haddan tashqari tekshirish testlarni mo‘rt qiladi: ishlab chiqarish kodida chaqiruvlar tartibining o‘zgarishi xatti-harakatni o‘zgartirmasdan testlarni buzadi.
Tez-tez beriladigan savollar
Stub ma’lumotlarni qaytaradi va holatni tekshiradi (nima qaytarildi), Mock esa xulq-atvorni tekshiradi (qaysi metodlar chaqirildi). Stub = „X ni qaytar“, Mock = „Y ning Z argumenti bilan chaqirilganini tekshir“. Haqiqiy testlarda bir ob'ekt ko‘pincha ham Stub, ham Mock rolini o‘ynaydi.
Fake Mock dan afzal, qachonki holatga bog‘liq mantiq test qilinayotgan bo‘lsa: keshlash, oflayn rejim, tranzaksiyalar. Fake (xotira ichidagi tatbiq) mo‘rt verify chaqiriqlarisiz bu ssenariylarni tekshirishga imkon beradi. Mock ma’lumot jo‘natishni tekshirish uchun ko‘proq mos keladi: analitika, push bildirishnomalari, elektron pochta.
Kotlin dagi Android loyihalari uchun MockK tavsiya etiladi. U qo‘shimcha sozlamalarsiz korutinlarni, suspend-funksiyalarni, sealed class va extension-funksiyalarni qo‘llab-quvvatlaydi. Java loyihalari uchun standart hali ham Mockito bo‘lib qolmoqda — keng hujjatlashtirishga ega eng mashhur kutubxona.
Kotlin Flow ni test qilish uchun MockK bilan birga Turbine kutubxonasidan foydalaning. Turbine Flow emissiyasini tekshirishni soddalashtiradi: qiymatlar tartibini, oqimning tugashini va istisnolarni tekshirish mumkin. Flow uchun Stub flowOf(value) qaytaradi, Mock Flow ning yig‘ilganligini tekshiradi.
Ha, lekin API javoblari darajasida, UI komponentlari emas. MockWebServer (OkHttp) va WireMock kutubxonalari UI testlarda HTTP javoblarini almashtirishga imkon beradi. UI komponentlarining o‘zi (Compose, SwiftUI Views) almashtirilmasligi kerak — ularning xatti-harakati screenshot testlari va Espresso orqali tekshiriladi.
Xulosa
Biz kalit topshirig'i bilan mobil ilovani ishlab chiqamiz
IT Sectr 2017-yildan beri startaplar va korxonalar uchun iOS va Android ilovalarini yaratadi. Biz sizga maslahat beramiz va eng yaxshi yechimni taklif qilamiz.