Stub (स्टब, टेस्ट डबल) — एक परीक्षण ऑब्जेक्ट जो वास्तविक कार्यान्वयन के बजाय मैथड कॉल्स पर पूर्वनिर्धारित प्रतिक्रियाएँ लौटाता है। मोबाइल डेवलपमेंट में, स्टब परीक्षित मॉड्यूल को नेटवर्क अनुरोधों, डेटाबेस और फ़ाइल सिस्टम से अलग करते हैं, जिससे पर्यावरण सेटअप के बिना तर्क की पुष्टि की जा सकती है। mock के विपरीत, stub व्यवहार की पुष्टि नहीं करता — यह केवल डेटा प्रदान करता है। अधिक जानकारी के लिए, देखें टेस्ट डबल्स पर Martin Fowler का लेख।
मुख्य बातें
Stub एक टेस्ट डबल ऑब्जेक्ट है जो परीक्षण में एक वास्तविक निर्भरता को बदलता है और विशिष्ट कॉल्स के लिए पूर्वनिर्धारित मान लौटाता है। यह शब्द Gerard Meszaros (2007) के वर्गीकरण में पुस्तक «xUnit Test Patterns» में पेश किया गया था। Stub test doubles की श्रेणी से संबंधित है — ऑब्जेक्ट जो परीक्षण के दौरान वास्तविक घटकों को बदलते हैं। स्टब का मुख्य उद्देश्य परीक्षित इकाई को पूर्वानुमानीय डेटा प्रदान करना है, बाहरी प्रणालियों से अनिश्चितता को हटाना।
कार्य विधि — परीक्षण निष्पादन से पहले स्टब को कॉन्फ़िगर करता है: «जब getUsers() मैथड कॉल किया जाए, तो उपयोगकर्ताओं की यह सूची लौटाओ»। Stub में कोई व्यावसायिक तर्क नहीं है, यह कॉल क्रम की पुष्टि नहीं करता और ना ही कॉल इतिहास रिकॉर्ड करता है। यह वास्तविक घटक के स्थान पर खड़ा होता है और जो उसे बताया गया है वह लौटाता है। Android परीक्षण के संदर्भ में, इसका मतलब है: OkHttp क्लाइंट सर्वर पर वास्तविक अनुरोध नहीं करता, बल्कि स्टब के रूप में कॉन्फ़िगर MockWebServer से प्रतिक्रिया प्राप्त करता है।
कब उपयोग करें — स्टब UI परत (ViewModel, Presenter) और व्यावसायिक तर्क (UseCase, Interactor) के परीक्षण के लिए आदर्श हैं, जहाँ आपको विशिष्ट डेटा पर प्रतिक्रिया की जाँच करने की आवश्यकता होती है: खाली सूची, सर्वर ने त्रुटि 500 लौटाई, टोकन समाप्त हो गया। कोई भी मामला जहाँ परीक्षण को एक विशिष्ट इनपुट स्थिति की आवश्यकता होती है, वह stub का कार्य है। प्रत्येक परीक्षण परिदृश्य की अपनी stub कॉन्फ़िगरेशन बनाई जाती है, जो परीक्षणों को पढ़ने में आसान और पूर्वानुमानीय बनाता है।
Gerard Meszaros (2007) ने पुस्तक «xUnit Test Patterns» में पाँच प्रकार के test doubles बताए: dummy, stub, spy, mock, fake। प्रत्येक प्रकार अपनी समस्या का समाधान करता है। Dummy — पास किया जाता है लेकिन उपयोग नहीं किया जाता। Stub — डेटा लौटाता है। Spy — कॉल्स रिकॉर्ड करता है। Mock — व्यवहार की पुष्टि करता है। Fake — सरल तर्क रखता है। इस वर्गीकरण को समझना डेवलपर को प्रत्येक परीक्षण परिदृश्य के लिए सही उपकरण चुनने में मदद करता है।
नेटवर्क अनुरोध — स्टब के उपयोग का सबसे सामान्य परिदृश्य। एप्लिकेशन API को HTTP कॉल करता है, और परीक्षण को विभिन्न प्रतिक्रियाओं पर प्रतिक्रिया की जाँच करने की आवश्यकता होती है: सफल JSON, 401 त्रुटि (अनधिकृत), टाइमआउट, खाली एरे। Android पर MockWebServer (OkHttp) और URLProtocol (iOS) स्टब के रूप में कार्य करते हैं, बिना वास्तविक सर्वर कनेक्शन के पूर्वनिर्धारित HTTP प्रतिक्रियाएँ लौटाते हैं। यह परीक्षणों को सेकंड से मिलीसेकंड तक तेज़ करता है।
डेटाबेस — Room (Android) और CoreData (iOS) में इन-मेमरी वारिएंट हैं, लेकिन उन्हें सेट अप करने में अभी भी समय लगता है। रिपॉजिटरी के बजाय Stub डेटाबेस को छुए बिना पूर्व तैयार Entity सूचियाँ लौटाता है। यह विशेष रूप से ViewModel के परीक्षण के लिए प्रभावी है, जहाँ आपको सॉर्टिंग, फ़िल्टरिंग या डेटा ट्रांसफ़र्मेशन की जाँच करने की आवश्यकता होती है। परीक्षण डेटा की मात्रा की परवाह किए बिना मिलीसेकंड में चलता है।
सिस्टम सेवाएँ — LocationManager, SensorManager, SharedPreferences के लिए एक वास्तविक डिवाइस या एमुलेटर की आवश्यकता होती है। LocationProvider के लिए Stub निर्दिष्ट निर्देशांक लौटाता है, SensorManager के लिए — एक्सेलेरोमीटर के निश्चित मान। iOS पर, एनालग परीक्षण डिलीगेट कार्यान्वयन के साथ CLLocationManager है। स्टब के बिना, एसे परीक्षणों के लिए विशिष्ट स्थितियों वाले भौतिक डिवाइस की आवश्यकता होती है।
फ़ाइल सिस्टम और कैश — इमेज लोडिंग, प्रतिक्रिया कैशिंग, कॉन्फ़िगरेशन फ़ाइलों के साथ काम — ये सभी ऑपरेशन डिस्क की स्थिति पर निर्भर करते हैं। FileManager या ImageCache के लिए Stub वास्तविक फ़ाइलें पढ़े बिना सफलता/त्रुटि लौटाता है। यह विभिन्न डेवलपर मशीनों पर पथ बेमेल या एक्सेस अधिकारों के कारण झूठी परीक्षण विफलताओं को समाप्त करता है।
उत्तरदायित्व का विभाजन — तीन प्रकार के test doubles अलग-अलग कार्य हल करते हैं। Stub: «मुझे डेटा दो»। Mock: «पुष्टि करो कि मुझे बुलाया गया»। Fake: «मैं असली की तरह काम करता हूँ, बस सरल»। यह अंतर परीक्षण पढ़ने योग्यता के लिए महत्वपूर्ण है: यदि कोई परीक्षण mock का उपयोग करता है जहाँ stub की आवश्यकता है, तो यह परीक्षित परिदृश्य से असंबंधित verify कॉल्स से भरा होता है।
| विशेषता | Stub | Mock | Fake |
|---|---|---|---|
| उद्देश्य | डेटा प्रदान करना | अंतरक्रिया की पुष्टि करना | सरल कार्यान्वयन |
| तर्क | नहीं | नहीं | है (लेकिन सरल) |
| सत्यापन | नहीं | हाँ (verify) | अप्रत्यक्ष (स्थिति के माध्यम से) |
| लचीलापन | कम — निश्चित उत्तर | मध्यम | उच्च — तर्क अनुकूलित होता है |
| गति | अधिकतम | उच्च | मध्यम |
| उदाहरण | MockWebServer JSON लौटाता है | Mockito.verify(repository).save() | HashMap के साथ InMemoryRepository |
व्यावहारिक नियम — यदि परीक्षण यह जाँच रहा है कि परीक्षित घटक ने कौन सा डेटा प्राप्त किया — stub का उपयोग करें। यदि परीक्षण यह जाँच रहा है कि क्या घटक ने सही आर्गुमेंट्स के साथ निर्भरता की विधि को बुलाया — mock का उपयोग करें। यदि आप बस एक डेटाबेस को हैश टेबल से बदलना चाहते हैं — यह fake है। एक परीक्षण में प्रकारों को मिलाना इसे नाजुर बनाता है: जब कार्यान्वयन बदलता है, तो आपको stub और verify दोनों तर्क को फिर से लिखना होगा।
verify के साथ Stub — एक सामान्य गलती जहाँ डेवलपर एक stub सेट अप करता है और फिर verify(stub).method() जोड़ता है। Stub की परिभाषा के अनुसार उसे सत्यापित नहीं किया जाना चाहिए — सत्यापन के लिए mock है। यदि आपको यह जाँच करने की आवश्यकता है कि किसी विधि को विशिष्ट आर्गुमेंट्स के साथ बुलाया गया, तो Mockito.stub() के बजाय Mockito.mock() का उपयोग करें। यह पृथक्करण अन्य डेवलपरों के लिए परीक्षण के इरादे को स्पष्ट रखता है।
MockWebServer — Android और JVM पर HTTP स्टब बनाने के लिए एक OkHttp लाइब्रेरी। यह एक निर्दिष्ट पोर्ट पर एक स्थानीय HTTP सर्वर शुरू करता है जो OkHttp क्लाइंट अनुरोधों को इंटरसेप्ट करता है और पूर्वनिर्धारित प्रतिक्रियाएँ लौटाता है। सेटअप में तीन लाइनें लगती हैं: सर्वर बनाएं, प्रतिक्रिया को enqueue करें, इसे शुरू करें। परीक्षण पेजिनेशन या रिट्री के परिदृश्य के लिए एक के बाद एक कई प्रतिक्रियाएँ enqueue कर सकता है।
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 के लिए Mockito का एक विकल्प। MockK में स्टब coEvery (suspend फ़ंक्शन्स के लिए) और every (निर्दिष्ट फ़ंक्शन्स के लिए) के माध्यम से बनाए जाते हैं। MockWebServer के विपरीत, MockK पूरे HTTP स्तर के बजाय अलग-अलग निर्भरता विधियों को स्टब करता है। यह UseCase या Interactor के यूनिट परीक्षणों के लिए सुविधाजनक है, जहाँ निर्भरताएँ रिपॉजिटरी अबस्ट्रेक्शन्स होती हैं।
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() }
}
}
सबसे अच्छा अभ्यास — इंटेग्रेशन परीक्षणों के लिए MockWebServer (वास्तविक HTTP को इंटरसेप्ट करता है) का उपयोग करें, यूनिट परीक्षणों के लिए MockK (इंटरफ़ेस को स्टब करता है) का उपयोग करें। जो आप परीक्षण नहीं कर रहे हैं उसे स्टब न करें: यदि परीक्षण Repository की पुष्टि करता है, तो उसके अंदर OkHttp क्लाइंट को स्टब न करें — HTTP स्तर पर एक वास्तविक MockWebServer का उपयोग करें। यह नियम परीक्षणों को प्रासंगिक रखता है और रिफ़ैक्टरिंग के दौरान नाजुरी कम करता है।
Swift प्रोटोकॉल स्टब के रूप में — iOS-नेटिव दृष्टिकोण में, stub को एक परीक्षण संरचना को प्रतिस्थापित करके लागू किया जाता है जो निर्भरता प्रोटोकॉल का अनुसरण करता है। एक वास्तविक NetworkService के बजाय, परीक्षण को एक StubNetworkService प्राप्त होता है जो निश्चित डेटा लौटाता है। Swift एक स्थैतिक रूप से टाइप की गई भाषा है, इसलिए stub को उसी प्रोटोकॉल का पालन करना चाहिए जो वास्तविक सेवा करती है। कंपाइलर गारंटी देता है कि stub सभी आवश्यक विधियों को लागू करता है।
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 के लिए OCMock — पुराने iOS प्रोजेक्टों में स्टब और मॉक बनाने के लिए एक लाइब्रेरी। OCMock आर्गुमेंट्स और रिटर्न वैल्यूज के साथ स्टब विधियों का समर्थन करता है। आधुनिक Swift प्रोजेक्ट मैनुअल स्टब के साथ प्रोटोकॉल-आधारित दृष्टिकोण पसंद करते हैं — यह प्रत्येक विधि पर नियंत्रण देता है और बाहरी निर्भरताओं की आवश्यकता नहीं होती। OCMock उन परियोजनाओं के लिए एक विकल्प बना रहता है जहाँ सभी निर्भरताओं को प्रोटोकॉलिज़ करना आर्थिक रूप से व्यवहार्य नहीं है।
HTTP स्टब के लिए URLProtocol — URLProtocol की उपवर्ग के माध्यम से नेटवर्क अनुरोधों को इंटरसेप्ट करने के लिए iOS में एक सिस्टम तन्त्र। परीक्षण एक कस्टम URLProtocol पंजीकृत करता है जो URLSession को इंटरसेप्ट करता है और स्टब प्रतिक्रियाएँ लौटाता है। मैनुअल स्टब से लाभ: आपको एप्लिकेशन आर्किटेक्चर बदलने की आवश्यकता नहीं है — URLSession वास्तविक रहता है, लेकिन डेटा प्रोटोकॉल स्तर पर बदल दिया जाता है। नुकसान: स्पष्ट stub सेवा की तुलना में डीबग करना कठिन है।
अक्सर पूछे जाने वाले प्रश्न
Stub पूर्वनिर्धारित डेटा लौटाता है और यह जाँच नहीं करता कि कॉल हुआ या नहीं। Mock अतिरिक्त रूप से सत्यापित करता है कि विधि को सही आर्गुमेंट्स के साथ बुलाया गया (verify)। Stub सवाल «क्या लौटाना है» का जवाब देता है, Mock «क्या कॉल हुआ» का। स्थिति सत्यापन के लिए stub, अंतरक्रिया सत्यापन के लिए mock का उपयोग करें।
Fake की आवश्यकता तब होती है जब परीक्षण को एक कार्यशील (भले ही सरल) कार्यान्वयन की आवश्यकता होती है — उदाहरण के लिए, Room के बजाय एक इन-मेमरी डेटाबेस। Stub पूर्वनिर्धारित डेटा के साथ एकल परिदृश्य के लिए उपयुक्त है। यदि आप 10 परीक्षणों में एक ही stub दोहरा रहे हैं — संभवतः आपको Fake की आवश्यकता है। Fake डप्लिकेशन कम करता है क्योंकि तर्क एक ही क्लास में रहता है।
Android पर — MockK Kotlin ऑब्जेक्ट (object) के लिए mockkObject() का समर्थन करता है, जिसमें mockkStatic() के माध्यम से Java क्लास की स्थैतिक विधियाँ शामिल हैं। iOS पर — Swift स्थैतिक विधियों को सीधे स्टब नहीं किया जा सकता; static कॉल को प्रोटोकॉल के इंस्टेंस मैथड से बदलने के लिए प्रोटोकॉल और DI का उपयोग करें। स्थैतिक स्टब तकनीकी कर्ज़ हैं और नए कोड में इनसे बचना चाहिए।
MockWebServer (OkHttp) का उपयोग करें — यह एक स्थानीय HTTP सर्वर की तरह काम करता है जो प्रतिक्रियाओं को enqueue करता है। Retrofit के लिए, बेस URL को localhost:8080 से बदलना पर्याप्त है। Ktor के लिए, MockEngine का उपयोग करें — HttpStatement को बदलने के लिए एक अंनिर्मित तन्त्र। दोनों दृष्टिकोण वास्तविक इंटरनेट के बिना काम करते हैं और स्थिति कोड, बॉडी और प्रतिक्रिया हैडर पर पूरा नियंत्रण देते हैं।
Spy एक वास्तविक ऑब्जेक्ट को लपेटता है और कॉल्स रिकॉर्ड करता है, जबकि Stub निश्चित प्रतिक्रियाओं के साथ ऑब्जेक्ट को पूरी तरह बदल देता है। Spy वास्तविक कार्यान्वयन के आंशिक उपयोग की अनुमति देता है (अन्य विधियाँ जैसी हैं वैसे काम करती हैं), जबकि stub नहीं करता। यदि आपको यह जाँच करने की आवश्यकता है कि कोई विधि बुलाई गई लेकिन तर्क का कुछ हिस्सा निष्पादित होना चाहिए — stub नहीं, spy का उपयोग करें।
सारांश
हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे
IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।
यह भी पढ़ें