Fake एक निर्भरता का कार्यशील सरलीकृत कार्यान्वयन है जो एक वास्तविक घटक की तरह व्यवहार करता है, लेकिन उत्पादन बुनियादी ढांचे के बजाय इन-मेमोरी स्टोरेज या अन्य हल्के तंत्र का उपयोग करता है। Stub के विपरीत, fake में वास्तविक व्यावसायिक तर्क होता है — सॉर्टिंग, फ़िल्टरिंग, एग्रीगेशन — बस बाहरी प्रभावों के बिना। Room के बजाय इन-मेमोरी डेटाबेस या SharedPreferences के बजाय HashMap क्लासिक उदाहरण हैं। अधिक जानकारी Martin Fowler के test doubles वर्गीकरण में।
मुख्य बातें
Fake एक इंटरफ़ेस का पूर्ण लेकिन हल्का कार्यान्वयन है जो परीक्षण के लिए उपयुक्त है। यह शब्द Gerard Meszaros (2007) द्वारा पुस्तक “xUnit Test Patterns” में पेश किया गया था। Stub के विपरीत, जो हार्डकोडेड उत्तर लौटाता है, fake में निष्पादन योग्य कोड होता है: यह सूची को सॉर्ट कर सकता है, शर्त के अनुसार फ़िल्टर कर सकता है, रिकॉर्ड गिन सकता है। उत्पादन कार्यान्वयन से एकमात्र अंतर यह है कि fake इन-मेमोरी डेटा के साथ काम करता है और वास्तविक I/O संचालन नहीं करता है।
मुख्य लाभ गति है। Fake के साथ परीक्षण मिलीसेकंड में निष्पादित होते हैं क्योंकि डिस्क, नेटवर्क या डेटाबेस तक पहुंच नहीं होती है। इन-मेमोरी HashMap Room या CoreData की तुलना में 100–1000 गुना तेज काम करता है। साथ ही, fake वास्तविक व्यावसायिक तर्क का परीक्षण करता है: सॉर्टिंग, फ़िल्टरिंग, एग्रीगेशन — वह सब जो stub परीक्षण नहीं कर सकता क्योंकि stub केवल वही लौटाता है जो उसे बताया गया था। Fake यह विश्वास दिलाता है कि कोड डेटा को सही ढंग से संसाधित करता है, न कि केवल पूर्वनिर्धारित उत्तर प्राप्त करता है।
Fake Stub से बेहतर है — यदि परीक्षण के तहत घटक डेटा पर कई संचालन करता है (प्राप्त करना, फ़िल्टर करना, सॉर्ट करना, सहेजना), तो stub को प्रत्येक कॉल को अलग-अलग कॉन्फ़िगर करने की आवश्यकता होगी। Fake में तर्क स्वयं के अंदर होता है — परीक्षण बस विधियों को कॉल करता है और परिणाम की जांच करता है। IT Sectr में, हम यूनिट परीक्षणों में सभी रिपॉजिटरी के लिए fakes का उपयोग करते हैं: HashMap के साथ एक fake रिपॉजिटरी Mockito या MockK सेट किए बिना 90% परिदृश्यों को कवर करती है।
चयन मानदंड — निर्धारित करें कि परीक्षण क्या सत्यापित करता है: स्थिति या अंतःक्रिया। यदि परीक्षण स्थिति (कार्य का परिणाम) सत्यापित करता है और तर्क का उपयोग करता है — fake का उपयोग करें। यदि परीक्षण को केवल बिना तर्क के इनपुट डेटा की आवश्यकता है — stub पर्याप्त है। यदि परीक्षण सत्यापित करता है कि एक विधि कॉल की गई थी — mock का उपयोग करें। एक परीक्षण में test doubles के प्रकारों को मिलाना समझ को जटिल बनाता है और नाजुकता बढ़ाता है।
| मानदंड | Fake | Stub | Mock |
|---|---|---|---|
| तर्क है | हाँ (सरलीकृत) | नहीं | नहीं |
| गति | उच्च | अधिकतम | उच्च |
| व्यवहार सत्यापन | अप्रत्यक्ष | नहीं | हाँ (verify) |
| रखरखाव | प्रति इंटरफ़ेस एक वर्ग | प्रति परीक्षण कॉन्फ़िगर करें | प्रति परीक्षण कॉन्फ़िगर करें |
| यथार्थता | उच्च (कोड काम करता है) | निम्न (हार्डकोडेड डेटा) | मध्यम |
| गलत सकारात्मक जोखिम | निम्न | मध्यम | उच्च (नाजुक परीक्षण) |
एंटी-पैटर्न: Fake जो fake नहीं है — एक सामान्य गलती जब डेवलपर किसी ऑब्जेक्ट को fake कहता है जो वास्तव में stub या mock है। यदि आपका InMemoryUserRepository कोई तर्क (फ़िल्टरिंग, सॉर्टिंग) नहीं रखता है — यह fake नहीं है, बल्कि इन-मेमोरी स्टोरेज वाला stub है। Fake stub से निष्पादन योग्य तर्क की उपस्थिति से भिन्न होता है। यदि fake रिपॉजिटरी बस वही लौटाती है जो उसमें डाला गया था और डेटा को संसाधित नहीं करती है — mock या stub का उपयोग करें।
व्यावहारिक अनुशंसा — प्रत्येक रिपॉजिटरी या सेवा के लिए fake से शुरू करें। यदि fake 50 पंक्तियों से अधिक हो — इसे कई वर्गों में विभाजित करें। यदि fake की बिल्कुल आवश्यकता नहीं है (परीक्षण केवल निश्चित डेटा के साथ एक परिदृश्य सत्यापित करता है) — stub का उपयोग करें। यदि परीक्षण सत्यापित करता है कि कोई विधि विशिष्ट मापदंडों के साथ कॉल की गई थी — mock का उपयोग करें। पहले से चयन को अनुकूलित न करें: एक fake लिखें, और यदि यह अत्यधिक हो जाता है, तो किसी विशिष्ट परीक्षण में इसे stub से बदलें।
Room के लिए Fake रिपॉजिटरी — Android पर fake का एक विशिष्ट उदाहरण। UserRepository का उत्पादन कार्यान्वयन SQLite क्वेरी के साथ Room DAO का उपयोग करता है। Fake संस्करण MutableList या HashMap में डेटा संग्रहीत करता है और समान विधियों को लागू करता है: getUser(id), saveUser(user), deleteUser(id)। Fake में खोज, फ़िल्टरिंग और सॉर्टिंग तर्क होता है — उत्पादन रिपॉजिटरी के समान, लेकिन SQL के बिना। यह Room डेटाबेस सेट किए बिना ViewModel और UseCase का परीक्षण करने की अनुमति देता है।
class FakeUserRepository : UserRepository {
private val users = mutableListOf<User>()
override suspend fun getUser(id: String): User? {
return users.find { it.id == id }
}
override suspend fun saveUser(user: User) {
val index = users.indexOfFirst { it.id == user.id }
if (index >= 0) users[index] = user
else users.add(user)
}
override suspend fun search(query: String): List<User> {
return users.filter {
it.name.contains(query, ignoreCase = true)
}
}
}
Retrofit API के लिए Fake — MockWebServer (जो एक stub है, fake नहीं) के बजाय, आप एक ApiService कार्यान्वयन बना सकते हैं जो इन-मेमोरी संग्रह से डेटा लौटाता है। अंतर: MockWebServer HTTP को इंटरसेप्ट करता है और JSON लौटाता है, जबकि fake ApiService बिना सीरियलाइज़ेशन के Kotlin इंटरफ़ेस स्तर पर काम करता है। Fake तेज़ है (कोई JSON पार्सिंग नहीं) और डीबग करना आसान है (उसी प्रक्रिया में चलता है, टाइप किया हुआ)। उन परीक्षणों के लिए उपयुक्त जहां HTTP सिमैंटिक्स (स्थिति कोड, हेडर) महत्वपूर्ण नहीं हैं।
Swift में Fake — प्रोटोकॉल के माध्यम से बनाया जाता है। उत्पादन वर्ग वास्तविक तर्क (CoreData, URLSession) के साथ प्रोटोकॉल को लागू करता है। Fake संरचना इन-मेमोरी स्टोरेज और सरलीकृत तर्क के साथ उसी प्रोटोकॉल को लागू करती है। Swift मान सेमैंटिक्स वाली भाषा है, इसलिए fake संरचनाएं अपरिवर्तनीय और मल्टीथ्रेडेड परीक्षणों में सुरक्षित हैं। यह Android एनालॉग्स पर लाभ देता है: इन-मेमोरी डेटा तक पहुंच को सिंक्रोनाइज़ करने की आवश्यकता नहीं है।
protocol UserRepositoryProtocol {
func getUser(id: String) async -> User?
func saveUser(user: User) async
}
final class FakeUserRepository: UserRepositoryProtocol {
private var storage: [String: User] = [:]
func getUser(id: String) async -> User? {
return storage[id]
}
func saveUser(user: User) async {
storage[user.id] = user
}
}
final class UserViewModelTests: XCTestCase {
func test_save_and_load() async {
let fake = FakeUserRepository()
let vm = UserViewModel(repository: fake)
let user = User(id: "1", name: "Alice")
await vm.saveUser(user)
let loaded = await vm.getUser(id: "1")
XCTAssertEqual(loaded?.name, "Alice")
}
}
CoreData के लिए Fake — iOS प्रोजेक्ट्स में, आप description.type = NSInMemoryStoreType सेट करके इन-मेमोरी NSPersistentContainer बना सकते हैं। यह एक पूर्ण CoreData स्टैक है, लेकिन मेमोरी में चल रहा है। ऐसा fake SQLite फ़ाइल बनाए बिना NSFetchRequest, प्रेडिकेट और सॉर्ट का परीक्षण करने की अनुमति देता है। गति: इन-मेमोरी CoreData पर परीक्षण डिस्क-आधारित एनालॉग की तुलना में 5–10 गुना तेज चलते हैं। कमी: हर बार NSManagedObjectModel सेट करने की आवश्यकता होती है।
FakeURLProtocol — iOS पर नेटवर्क अनुरोधों को इंटरसेप्ट करने के लिए URLProtocol का एक उपवर्ग। इसे URLProtocol.registerClass(fakeProtocol) के माध्यम से पंजीकृत किया जाता है। आंतरिक रूप से इसमें इन-मेमोरी URL -> Data शब्दकोश होता है और बिना वास्तविक अनुरोध के डेटा लौटाता है। Stub से अंतर: FakeURLProtocol अनुरोध निकाय, हेडर की जांच कर सकता है और इनपुट डेटा के आधार पर अलग-अलग प्रतिक्रियाएं लौटा सकता है। यह fake है क्योंकि इसमें अनुरोध रूटिंग तर्क होता है।
Fake एक Test Fixture के रूप में — fake वर्गों को एक साझा परीक्षण मॉड्यूल (androidTest/sharedTest या TestSupport) में रखें। प्रोजेक्ट के सभी परीक्षण उसी InMemoryUserRepository का उपयोग करते हैं। यह प्रत्येक परीक्षण में mock ऑब्जेक्ट सेटअप के दोहराव को समाप्त करता है और एक समान व्यवहार की गारंटी देता है। Fake तर्क को बदलना सभी परीक्षणों को एक साथ अपडेट करता है। IT Sectr में, हम fake वर्गों को sharedTest/java/com/itSectr/fake/ में संग्रहीत करते हैं और उन्हें implementation project(:sharedTest) के माध्यम से शामिल करते हैं।
पूर्वनिर्धारित डेटा के साथ Fake — अक्सर परीक्षणों को एक ऐसी रिपॉजिटरी की आवश्यकता होती है जिसमें पहले से ही कुछ रिकॉर्ड हों। समाधान: एक फैक्ट्री विधि fakeWithData(vararg items) या एक अंतर्निहित addDefaultData() विधि। फैक्ट्री एक fake बनाती है, उसे विशिष्ट डेटा से भरती है और उपयोग के लिए तैयार ऑब्जेक्ट लौटाती है। यह परीक्षणों में बॉयलरप्लेट को कम करता है: mock कॉल सेट करने के बजाय, परीक्षण बस FakeUserRepository.withUsers(alice, bob) को कॉल करता है।
कॉल गिनती के साथ Fake — कभी-कभी न केवल स्थिति बल्कि कॉल की संख्या को भी सत्यापित करने की आवश्यकता होती है। Fake में काउंटर हो सकते हैं: saveCallCount, getUserCallCount। परीक्षण निष्पादन के बाद काउंटर की जांच करता है। यह शुद्ध fake (स्थिति सत्यापन) और mock (अंतःक्रिया सत्यापन) के बीच एक समझौता है। काउंटर तर्क या कॉल क्रम की जांच नहीं करते — केवल संख्या। तर्क सत्यापन के लिए, mock का उपयोग करें।
Callback के साथ Fake — अतुल्यकालिक परिदृश्यों के परीक्षण के लिए, fake प्रत्येक कॉल पर एक callback स्वीकार कर सकता है: beforeGetUser, afterSaveUser। यह देरी, त्रुटियों का अनुकरण करने या मध्यवर्ती स्थितियों की जांच करने की अनुमति देता है। यह दृष्टिकोण UI लोडिंग स्थितियों के परीक्षण के लिए उपयोगी है: fake 100 ms के लिए रुकता है, और परीक्षण सत्यापित करता है कि स्क्रीन लोडर दिखाती है। Callback उत्पादन में अनुपस्थित है — यह पूरी तरह से परीक्षण कार्यक्षमता है।
अक्सर पूछे जाने वाले प्रश्न
Fake में कार्यशील तर्क होता है — फ़िल्टर करता है, सॉर्ट करता है, गिनता है। Stub बिना तर्क के केवल पूर्वनिर्धारित उत्तर लौटाता है। यदि किसी ऑब्जेक्ट में शाखाएं (if/else, when) हैं — यह fake है। यदि इसमें केवल रिटर्न वैल्यू हैं — यह stub है। Fake रखरखाव में अधिक महंगा है लेकिन अधिक यथार्थवादी परीक्षण प्रदान करता है।
जब fake तर्क उत्पादन तर्क से मेल नहीं खाता। उदाहरण के लिए, FakeUserRepository केस-सेंसिटिव खोज का उपयोग करता है, जबकि उत्पादन संस्करण केस-इनसेंसिटिव है। परीक्षण पास हो जाता है, लेकिन वास्तविकता में बग है। समाधान: fake तर्क को अलग से परीक्षण करें या केवल सरल तर्क (CRUD संचालन) वाले इंटरफ़ेस के लिए fakes का उपयोग करें। जटिल तर्क के लिए, वास्तविक डेटाबेस के साथ एकीकरण परीक्षण लिखें।
इन-मेमोरी डेटाबेस fake का एक प्रकार है। Room.inMemoryDatabaseBuilder() इन-मेमोरी SQLite बनाता है जो उत्पादन डेटाबेस की तरह व्यवहार करता है। यह एक पूर्ण fake है। लेकिन fake रिपॉजिटरी स्तर (SQL के बिना) और नेटवर्क स्तर (FakeApiService) पर भी हो सकता है। इन-मेमोरी डेटाबेस fake का एक विशेष मामला है जहां तर्क यथासंभव वास्तविक के करीब है।
हाँ, लेकिन सावधानी के साथ। Fake रिपॉजिटरी के लिए (डेटा), Mock AnalyticsTracker के लिए (घटना सत्यापन)। परतों द्वारा पृथक्करण: डेटा परत के लिए fake, विश्लेषण/लॉगिंग परत के लिए mock। एक ऑब्जेक्ट को एक साथ fake और mock न बनाएं — यह एकल जिम्मेदारी सिद्धांत का उल्लंघन करता है और परीक्षण को भ्रमित करता है।
Fake का परीक्षण उत्पादन कार्यान्वयन के समान परीक्षणों से करें। यदि आपके पास UserRepositoryTest है जो save, get, delete सत्यापित करता है — इसे दो बार चलाएं: FakeUserRepository के साथ और RealUserRepository के साथ। यह गारंटी देता है कि fake उत्पादन वर्ग के व्यवहार को दोहराता है। यदि fake अलग व्यवहार करना शुरू करता है — परीक्षण दोनों कार्यान्वयनों पर विफल हो जाएगा।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें