Mock — यह क्या है, मॉक ऑब्जेक्ट और टेस्टिंग के लिए लाइब्रेरीज़

लेखक: IT Sectr प्रकाशित: 2026-04-10 पढ़ने का समय: 8 मिनट

Mock एक विकल्पी ऑब्जेक्ट है जो वास्तविक घटक के व्यवहार का अनुकरण करता है और इसके साथ इंटरैक्शन की जाँच करने की अनुमति देता है। Stub के विपरीत, जो केवल एक पूर्वनिर्धारित मान लौटाता है, Mock विधि के आह्वान, पारित किए गए आर्गुमेंट और कॉल की संख्या को रिकॉर्ड करता है। Mockito (2024) के अनुसार, Mock Java और Kotlin प्रोजेक्ट्स में सबसे लोकप्रिय Test Double प्रकार है, जिसका उपयोग मोबाइल एप्लिकेशन के 70% से अधिक यूनिट टेस्ट में किया जाता है।

मुख्य बिंदु

  • Mock — एक ऑब्जेक्ट जो इंटरैक्शन की जाँच करता है: कौन सी विधियाँ कॉल की गईं, किन आर्गुमेंट के साथ और कितनी बार
  • Mockito — Java और Android प्रोजेक्ट्स में Mock बनाने के लिए सबसे लोकप्रिय लाइब्रेरी
  • MockK — Kotlin के लिए Mockito का विकल्प, कोरूटीन और सील्ड क्लास के लिए मूल समर्थन के साथ
  • Behavior verification — Mock और Stub के बीच मुख्य अंतर: Mock व्यवहार की जाँच करता है, स्थिति की नहीं
  • Over-mocking — मुख्य एंटी-पैटर्न: mock केवल बाहरी निर्भरताओं के लिए होना चाहिए

Mock क्या है?

Mock एक ऑब्जेक्ट है जो मॉकिंग फ्रेमवर्क (Mockito, MockK, EasyMock) द्वारा बनाया जाता है, जो एक इंटरफ़ेस या क्लास का अनुकरण करता है और अपनी विधियों के सभी कॉल रिकॉर्ड करता है। डेवलपर अपेक्षाएँ निर्धारित करता है: विधि X को आर्गुमेंट Y के साथ कॉल किया जाएगा और Z लौटाएगा। टेस्ट निष्पादित होने के बाद, Mock जाँचता है कि अपेक्षाएँ वास्तविक कॉल से मेल खाती हैं या नहीं।

यह शब्द Test Doubles के नाटकीय रूपक से आया है: Mock एक «अनुकरणकर्ता» है जो केवल मंच पर खड़ा नहीं होता (Dummy की तरह) बल्कि एक भूमिका निभाता है और जाँचता है कि उसके साथ इंटरैक्शन सही था या नहीं। यदि परीक्षण के तहत कोड ने उस विधि को कॉल नहीं किया जिसकी Mock अपेक्षा कर रहा था, या गलत आर्गुमेंट के साथ कॉल किया — तो टेस्ट उल्लंघित अपेक्षा के संदेश के साथ विफल हो जाता है।

Mock कैसे काम करता है

Mock फ्रेमवर्क फैक्ट्री के माध्यम से बनाया जाता है: mockk<MyInterface>() या Mockito.mock(MyClass.java)। फ्रेमवर्क एक प्रॉक्सी ऑब्जेक्ट उत्पन्न करता है जो सभी विधि कॉल को इंटरसेप्ट करता है। प्रत्येक कॉल की तुलना पूर्वनिर्धारित अपेक्षाओं से की जाती है। यदि कॉल अपेक्षा से मेल खाता है — निर्दिष्ट मान लौटाया जाता है। यदि नहीं — Mock कॉन्फ़िगरेशन के आधार पर डिफ़ॉल्ट मान लौटाता है या अपवाद फेंकता है।

Mock कब आवश्यक है

Mock आवश्यक है जब परीक्षण के तहत कोड ऐसे घटकों के साथ इंटरैक्ट करता है जिनके दुष्प्रभाव होते हैं: सर्वर पर डेटा भेजना, डेटाबेस में लिखना, लॉगिंग, analytics, नेविगेशन, सिस्टम डायलॉग दिखाना। Mock के बिना, वास्तविक बुनियादी ढाँचा चलाए बिना इन इंटरैक्शन की जाँच नहीं की जा सकती। Google Testing Blog के अनुसार, Mock यह जाँचने का एकमात्र तरीका है कि किसी एप्लिकेशन ने वास्तव में टेस्ट सर्वर चालू किए बिना analytics इवेंट भेजा है।

Mock बनाम Stub: विस्तृत तुलना

Mock और Stub के बीच अंतर टेस्टिंग में सबसे विवादास्पद विषयों में से एक है। दोनों प्रकार वास्तविक निर्भरता को बदलते हैं, लेकिन मौलिक रूप से भिन्न तरीकों से।

मापदंडMockStub
मुख्य प्रश्नक्या विधि कॉल की गई?क्या परिणाम लौटाया गया?
सत्यापनव्यवहार (verify)स्थिति (assert)
डेटा वापसीवैकल्पिकअनिवार्य
उदाहरणverify(analytics).logEvent(“click”)assertEquals(5, repository.getCount())
कब उपयोग करेंदुष्प्रभावडेटा वापसी

व्यावहारिक नियम: Mock या नहीं

चुनाव के लिए एक सरल परीक्षण: अपने आप से पूछें «यदि मैं कोड की इस पंक्ति को हटा दूँ, तो क्या टेस्ट विफल होगा?» यदि टेस्ट रिटर्न वैल्यू की जाँच करता है — आपको Stub चाहिए (assert-आधारित सत्यापन)। यदि टेस्ट जाँचता है कि कोड ने सही आर्गुमेंट के साथ विधि को कॉल किया — आपको Mock चाहिए (verify-आधारित सत्यापन)। यह द्वंद्व Command-Query Separation पैटर्न का अनुसरण करता है: जो विधियाँ स्थिति बदलती हैं (commands) उन्हें Mock चाहिए; जो विधियाँ डेटा लौटाती हैं (queries) उन्हें Stub चाहिए।

Mockito बनाम MockK: लाइब्रेरी तुलना

Mockito और MockK के बीच चुनाव Kotlin में Android प्रोजेक्ट के टेस्ट स्टैक को स्थापित करते समय पहले निर्णयों में से एक है। दोनों लाइब्रेरीज़ एक ही उद्देश्य पूरा करती हैं, लेकिन Kotlin-विशिष्ट सुविधाओं के प्रति अलग-अलग दृष्टिकोण के साथ।

Mockito: सिद्ध क्लासिक

Mockito Java प्रोजेक्ट्स के लिए वास्तविक मानक है। संस्करण 5.x बिल्ट-इन MockMaker की बदौलत फ़ाइनल क्लास, स्टैटिक विधियों और कंस्ट्रक्टर के लिए मॉकिंग का समर्थन करता है। Kotlin प्रोजेक्ट्स के लिए, Mockito को अतिरिक्त सेटअप की आवश्यकता होती है: बेहतर सिंटैक्स के लिए mockito-kotlin एक्सटेंशन, फ़ाइनल क्लास के लिए mockito-inline। Mockito अतिरिक्त एडॉप्टर के बिना Kotlin कोरूटीन और suspend फ़ंक्शन का समर्थन नहीं करता।

MockK: Kotlin-प्रथम दृष्टिकोण

MockK विशेष रूप से Kotlin के लिए बनाया गया था। यह मूल रूप से कोरूटीन (coEvery, coVerify), सील्ड क्लास, डेटा क्लास, ऑब्जेक्ट सिंगलटन और एक्सटेंशन फ़ंक्शन का समर्थन करता है। MockK सिंटैक्स लैम्ब्डा ब्लॉक के साथ DSL का उपयोग करता है, जो Kotlin कोड में स्वाभाविक लगता है। MockK बिना अतिरिक्त सेटअप के प्रॉपर्टी मॉकिंग का भी समर्थन करता है — यह Android प्रोजेक्ट्स के लिए महत्वपूर्ण है जो LiveData, StateFlow और Delegates का उपयोग करते हैं।

kotlin
// Mockito + mockito-kotlin
val repository = mock<UserRepository>()
whenever(repository.getUser(1)).thenReturn(user)

// MockK
val repository = mockk<UserRepository>()
every { repository.getUser(1) } returns user

प्रदर्शन तुलना

बेंचमार्क (JVM Benchmark, 2024) दिखाते हैं कि MockK Java Reflections के बजाय Kotlin बाइटकोड के साथ सीधे काम करने के कारण Kotlin प्रोजेक्ट्स के लिए Mockito की तुलना में 15–20% तेज़ी से मॉक ऑब्जेक्ट बनाता है। हज़ारों यूनिट टेस्ट वाले प्रोजेक्ट्स के लिए, बिल्ड स्पीड में अंतर ध्यान देने योग्य हो सकता है: MockK बड़े प्रोजेक्ट्स में पूर्ण टेस्ट रन पर 30–60 सेकंड बचाता है।

Kotlin में Mock टेस्ट के उदाहरण

तीन परिदृश्यों की जाँच करें: Mock निर्भरताओं के साथ ViewModel का परीक्षण, API कॉल सत्यापन के साथ UseCase का परीक्षण, और coVerify के साथ कोरूटीन का परीक्षण।

उदाहरण 1: Mock analytics के साथ ViewModel

kotlin
class ProfileViewModelTest {
    private val analytics = mockk<AnalyticsService>()
    private val repo = mockk<UserRepository>()
    private val vm = ProfileViewModel(repo, analytics)

    fun `profile opened logs analytics event`() {
        every { analytics.logEvent("profile_opened") } returns Unit

        vm.onViewCreated()

        verify { analytics.logEvent("profile_opened") }
    }
}

उदाहरण 2: अतुल्यकालिक सत्यापन के साथ UseCase

kotlin
class SendMessageUseCaseTest {
    private val api = mockk<MessagingApi>()
    private val useCase = SendMessageUseCase(api)

    fun `send message with correct payload`() = runTest {
        val message = Message(text = "Hello", userId = 42)

        coEvery { api.sendMessage(any()) } returns MessageResult.Sent("msg_1")

        val result = useCase.execute(message)

        coVerify {
            api.sendMessage(match {
                it.text == "Hello" && it.userId == 42
            })
        }
        assertTrue(result is MessageResult.Sent)
    }
}

उदाहरण 3: ArgumentCaptor के साथ आर्गुमेंट सत्यापन

kotlin
class OrderUseCaseTest {
    private val api = mockk<OrderApi>()
    private val useCase = OrderUseCase(api)
    private val slot = slot<OrderRequest>()

    fun `order request contains correct items`() = runTest {
        coEvery { api.placeOrder(capture(slot)) } returns OrderResult.Placed("order_1")

        useCase.execute(listOf("item_a", "item_b"))

        assertEquals(2, slot.captured.items.size)
        assertEquals("item_a", slot.captured.items[0])
    }
}

Mock टेस्टिंग के सर्वोत्तम अभ्यास

मोबाइल डेवलपमेंट में Mock का प्रभावी उपयोग अनुशासन की आवश्यकता है। इन नियमों का उल्लंघन टेस्ट को नाजुक बाधाओं में बदल देता है जो हर रिफैक्टरिंग के साथ टूट जाते हैं।

केवल बाहरी एप्लिकेशन सीमाओं का Mock करें

एक सख्त नियम: Mock केवल उन निर्भरताओं के लिए बनाए जाने चाहिए जो एप्लिकेशन सीमा को पार करती हैं: API क्लाइंट, डेटाबेस, फ़ाइल सिस्टम, सिस्टम सेवाएँ (LocationManager, BluetoothAdapter, Camera)। आंतरिक एप्लिकेशन क्लास — डोमेन एंटिटीज़, Value Objects, सरल उपयोगिताएँ — को Mock से प्रतिस्थापित नहीं किया जाना चाहिए। उनके व्यवहार का परीक्षण वास्तविक ऑब्जेक्ट के माध्यम से किया जाता है।

एक टेस्ट में एक assert / verify

प्रत्येक टेस्ट में बिल्कुल एक तार्किक जाँच होनी चाहिए — या तो verify (Mock के लिए) या assert (Stub के लिए)। एक ही टेस्ट में स्थिति और व्यवहार सत्यापन को न मिलाएँ। यदि आपको API कॉल और उसके परिणाम दोनों की जाँच करनी है — अलग-अलग नामों के साथ दो अलग टेस्ट बनाएँ। यह नियम, जिसे «एक टेस्ट में एक assert» के रूप में जाना जाता है, Kent Beck (2002) की सिफारिशों से आता है।

  • MockK में Unit लौटाने वाली विधियों के लिए relaxUnitFun = true का उपयोग करें — अन्यथा Mock अपरिभाषित कॉल पर अपवाद फेंकेगा
  • verify को केवल महत्वपूर्ण कॉल तक सीमित रखें — हर getter और setter की जाँच न करें, यह टेस्ट को नाजुक बनाता है
  • ArgumentMatchers का सोच-समझकर उपयोग करें — any() महत्वपूर्ण विवरण छिपाता है यदि आर्गुमेंट व्यावसायिक तर्क के लिए महत्वपूर्ण है
  • verifyNoMoreInteractions का अत्यधिक उपयोग न करें — यह विधि टेस्ट को प्रोडक्शन कोड में किसी भी बदलाव के प्रति अनावश्यक रूप से कठोर बनाती है
  • @MockkAnnotations का उपयोग करें Mock ऑब्जेक्ट के स्वचालित आरंभीकरण के लिए — यह बॉयलरप्लेट कम करता है और पठनीयता में सुधार करता है

Mock टेस्टिंग की उन्नत तकनीकें

बुनियादी मॉकिंग के अलावा, उन्नत तकनीकें हैं जो मोबाइल डेवलपमेंट में विशिष्ट कार्यों को हल करती हैं: मल्टीथ्रेडिंग का परीक्षण, Flow स्थिति की जाँच, और वास्तविक ऑब्जेक्ट का आंशिक मॉकिंग।

spyK के साथ आंशिक Mock

Spy (या आंशिक mock) एक ऑब्जेक्ट बनाने की अनुमति देता है जो कॉल को वास्तविक कार्यान्वयन को सौंपता है लेकिन व्यक्तिगत विधियों को ओवरराइड करने देता है। MockK में, spyk एक वास्तविक क्लास इंस्टेंस के आधार पर बनाया जाता है: val repo = spyk(InMemoryUserRepository())every के माध्यम से परिभाषित अपेक्षाओं वाले कॉल Mock के माध्यम से जाते हैं; बाकी वास्तविक ऑब्जेक्ट के माध्यम से जाते हैं। Spy विशेष रूप से लीगेसी कोड के परीक्षण के लिए उपयोगी है जहाँ डिपेंडेंसी इंजेक्शन अभी तक लागू नहीं हुआ है और आपको केवल एक विधि को ओवरराइड करने की आवश्यकता है।

Turbine के साथ StateFlow का परीक्षण

Jetpack Compose का उपयोग करने वाले आधुनिक Android प्रोजेक्ट्स में, ViewModel StateFlow के माध्यम से स्थिति प्रदर्शित करता है। MockK Flow निर्भरताओं को मॉक करने की अनुमति देता है, और Turbine लाइब्रेरी उत्सर्जन सत्यापन को सरल बनाती है। क्लासिक पैटर्न: Flow लौटाने वाले UseCase के लिए MockK, ViewModel उत्सर्जन की जाँच के लिए Turbine। यह स्टैक Kotlin Coroutines का उपयोग करने वाले प्रोजेक्ट्स के लिए Android Testing प्रलेखन (Google, 2024) द्वारा अनुशंसित है।

kotlin
class SearchViewModelTest {
    private val searchUseCase = mockk<SearchUseCase>()
    private val vm = SearchViewModel(searchUseCase)

    fun `search emits results`() = runTest {
        coEvery { searchUseCase.search("android") } returns
            flowOf(SearchResult.Success(listOf(Item("Android TDD"))))

        vm.search("android")

        vm.state.test {
            val state = awaitItem()
            assertTrue(state.items.isNotEmpty())
            cancelAndIgnoreRemainingEvents()
        }
    }
}

अक्सर पूछे जाने वाले प्रश्न

Mock, Mockito से कैसे भिन्न है?

Mock एक अवधारणा है, Test Double का एक प्रकार जो व्यवहार की जाँच करता है। Mockito Java और Android में Mock ऑब्जेक्ट बनाने के लिए एक लाइब्रेरी है। अन्य लाइब्रेरीज़: MockK (Kotlin), EasyMock (Java), Cuckoo (iOS)।

Mock Kotlin कोरूटीन के साथ कैसे काम करता है?

Mock के साथ suspend फ़ंक्शन के परीक्षण के लिए MockK (coEvery / coVerify) या mockito-kotlin के साथ Mockito का उपयोग करें। MockK मूल रूप से कोरूटीन का समर्थन करता है: coEvery suspend फ़ंक्शन के व्यवहार को परिभाषित करता है, coVerify कोरूटीन के अंदर इसके कॉल की जाँच करता है। सभी suspend कॉल को runTest (kotlinx-coroutines-test) के अंदर निष्पादित किया जाना चाहिए।

क्या Mock बार-बार कॉल करने पर अलग-अलग मान लौटा सकता है?

हाँ। MockK में, returnsMany का उपयोग करें: every { api.getData() } returnsMany listOf(response1, response2)Mockito में — thenReturn(value1).thenReturn(value2) की श्रृंखला। यह अनुक्रमिक कॉल के साथ अलग-अलग प्रतिक्रियाएँ लौटाने वाले व्यवहार के परीक्षण के लिए उपयोगी है।

परीक्षणों के बीच Mock की स्थिति कैसे साफ़ करें?

MockK में, relaxed = true के साथ @MockK एनोटेशन का उपयोग करें और @After विधि में clearMocks(mock) कॉल करें। Mockito में — Mockito.reset(mock)। सर्वोत्तम अभ्यास: क्रॉस-टेस्ट हस्तक्षेप को खत्म करने के लिए @Before के माध्यम से प्रत्येक टेस्ट के लिए नया Mock बनाएँ।

Mock Kotlin में सील्ड क्लास को कैसे संभालता है?

MockK सील्ड क्लास के साथ सही ढंग से काम करता है: every { useCase() } returns Result.Success(data)Mockito सीधे सील्ड क्लास का समर्थन नहीं करता, जिसके लिए वर्कअराउंड की आवश्यकता होती है। यह एक कारण है कि Kotlin प्रोजेक्ट्स के लिए Mockito के बजाय MockK की सिफारिश की जाती है।

सारांश

  • Mock — एक Test Double प्रकार जो निर्भरताओं के व्यवहार (verify) की जाँच करता है, स्थिति (assert) की नहीं
  • Mockito — Java/Android के लिए मानक, MockK — कोरूटीन और सील्ड क्लास के समर्थन के साथ Kotlin-प्रथम विकल्प
  • मुख्य नियम: बाहरी सीमाओं (नेटवर्क, DB, सिस्टम सेवाओं) के लिए Mock, आंतरिक क्लास के लिए वास्तविक ऑब्जेक्ट
  • Over-mocking — मुख्य एंटी-पैटर्न: अत्यधिक निर्भरता प्रतिस्थापन टेस्ट को नाजुक और बेकार बनाता है
  • एक टेस्ट — एक तार्किक जाँच: Mock के लिए verify या Stub के लिए assert, एक ही टेस्ट में दोनों नहीं
  • ArgumentCaptor / slot — अंधे any() के बजाय Mock कॉल आर्गुमेंट की जाँच करने का सही तरीका
  • MockK Kotlin प्रोजेक्ट्स के लिए अनुशंसित है: coEvery और coVerify बिना अतिरिक्त एडॉप्टर के मूल रूप से कोरूटीन के साथ काम करते हैं

हम एक मोबाइल एप्लिकेशन टर्नकी विकसित करेंगे

IT Sectr 2017 से स्टार्टअप और व्यवसायों के लिए iOS और Android एप्लिकेशन बनाता है। हम आपको सलाह देंगे और सर्वोत्तम समाधान प्रस्तावित करेंगे।

परियोजना पर चर्चा करें

यह भी पढ़ें