कैसे (जब) ​​मंगलाचरण काम करता है?


111

निम्नलिखित मॉकिटो कथन को देखते हुए:

when(mock.method()).thenReturn(someValue);

मॉकिटो एक मॉक के लिए कुछ समीपवर्ती बनाने के बारे में कैसे जाता है, यह देखते हुए कि मॉकमिथोड () स्टेटमेंट कब () को रिटर्न वैल्यू पास करेगा? मुझे लगता है कि यह कुछ सीजीएलआईबी सामान का उपयोग करता है, लेकिन यह जानने के लिए दिलचस्पी होगी कि यह तकनीकी रूप से कैसे किया जाता है।

जवाबों:


118

संक्षिप्त उत्तर यह है कि आपके उदाहरण में, परिणाम का mock.method()प्रकार एक उपयुक्त उपयुक्त रिक्त मान होगा; मॉकिटो अप्रत्यक्ष रूप से प्रॉक्सिमिंग, विधि अवरोधन और MockingProgressकक्षा के साझा उदाहरण के माध्यम से यह निर्धारित करने के लिए उपयोग करता है कि मॉक पर किसी विधि का आह्वान स्टबिंग या मौजूदा स्टब्ड व्यवहार के पुनरावृत्ति के लिए है, बजाय वापसी के मूल्य के बारे में स्टबिंग से गुजरने के लिए एक मजाकिया तरीका।

मॉकिटो कोड को देखने वाले कुछ मिनटों में एक मिनी-विश्लेषण इस प्रकार है। ध्यान दें, यह एक बहुत ही मोटा विवरण है - यहां खेलने के लिए बहुत सारे विवरण हैं। मेरा सुझाव है कि आप स्वयं गीथूब पर स्रोत की जाँच करें।

सबसे पहले, जब आप क्लास के mockतरीके का उपयोग करके क्लास का मजाक उड़ाते हैं, तो Mockitoअनिवार्य रूप से यही होता है:

  1. Mockito.mockorg.mockito.internal.MockitoCoreएक पैरामीटर के रूप में डिफ़ॉल्ट मॉक सेटिंग्स को पारित करने के लिए .mock को दर्शाता है।
  2. MockitoCore.mockप्रतिनिधियों को org.mockito.internal.util.MockUtil.createMock
  3. MockUtilक्लास का उपयोग ClassPathLoaderका एक उदाहरण प्राप्त करने के लिए वर्ग MockMakerनकली बनाने के लिए उपयोग करने के लिए। डिफ़ॉल्ट रूप से, CgLibMockMaker वर्ग का उपयोग किया जाता है।
  4. CgLibMockMakerJMock से उधार ली गई एक क्लास का उपयोग करता है, ClassImposterizerजो मॉक बनाने का काम करता है। 'Mockito जादू' का इस्तेमाल किया के प्रमुख टुकड़े कर रहे हैं MethodInterceptormockito: नकली बनाने के लिए इस्तेमाल MethodInterceptorFilter, और का एक उदाहरण सहित MockHandler उदाहरणों की शृंखला MockHandlerImpl । विधि इंटरसेप्टर मॉकहैंडलरइम्पल उदाहरण के लिए इनवोकेशन पास करता है, जो कि बिजनेस लॉजिक को लागू करता है, जिसे एक मॉक पर मंगाने पर लागू किया जाना चाहिए (यानी, यह देखने के लिए कि क्या जवाब पहले से रिकॉर्ड किया गया है, यह निर्धारित करते हुए कि इन्वोकेशन नए स्टब का प्रतिनिधित्व करता है, आदि। डिफ़ॉल्ट स्थिति यह है कि यदि एक स्टब पहले से ही लागू होने वाली विधि के लिए पंजीकृत नहीं है, तो एक प्रकार का उपयुक्त खाली मान वापस किया जाता है।

अब, अपने उदाहरण में कोड को देखें:

when(mock.method()).thenReturn(someValue)

यहां यह आदेश दिया गया है कि यह कोड इस पर अमल करेगा:

  1. mock.method()
  2. when(<result of step 1>)
  3. <result of step 2>.thenReturn

यह समझने की कुंजी है कि मॉक पर विधि लागू होने पर क्या होता है: विधि इंटरसेप्टर को विधि मंगलाचरण के बारे में जानकारी दी जाती है, और इसके MockHandlerउदाहरणों की श्रृंखला को सौंपता है, जो अंततः प्रतिनिधि को सौंपता है MockHandlerImpl#handle। इस दौरान MockHandlerImpl#handle, मॉक हैंडलर एक इंस्टेंस बनाता है OngoingStubbingImplऔर इसे साझा MockingProgressइंस्टेंस पर भेजता है।

जब whenआह्वान के बाद विधि का इस्तेमाल किया जाता है method(), तो यह उसी वर्ग MockitoCore.whenकी stub()पद्धति को बुलाता है । यह विधि साझा किए गए MockingProgressइंस्टेंस से चल रहे स्टबिंग को अनपैक करती है जिसे मॉकडाउन method()इनवोकेशन में लिखा गया है, और इसे वापस लौटाता है। फिर thenReturnविधि को फिर OngoingStubbingउदाहरण पर बुलाया जाता है ।


1
विस्तृत प्रतिक्रिया के लिए धन्यवाद। एक और सवाल - आप उल्लेख करते हैं कि "जब विधि के आह्वान के बाद विधि का आह्वान किया जाता है ()" - यह कैसे पता चलता है कि कब () का आह्वान विधि का आह्वान है? आशा है कि समझ में आता है।
११:००

@marchaos यह नहीं जानता। when(mock.method()).thenXyz(...)सिंटैक्स के साथ , mock.method()"रीप्ले" मोड में निष्पादित होता है, "स्टबिंग" मोड में नहीं। आम तौर पर, इस निष्पादन mock.method()कोई प्रभाव नहीं है, इसलिए बाद में जब thenXyz(...)( thenReturn, thenThrow, thenAnswer, आदि) को मार डाला जाता है, यह मोड "छोटा करते" में चला जाता है और फिर उस विधि कॉल के लिए वांछित परिणाम रिकॉर्ड करता है।
रोजेरियो

1
रोजेरियो, यह वास्तव में उससे थोड़ा अधिक सूक्ष्म है - मॉकिटो में स्पष्ट स्टबिंग और रीप्ले मोड नहीं हैं। मैं अपने उत्तर को बाद में संपादित करूँगा ताकि यह अधिक स्पष्ट हो।
पॉल मोरी

मैं कहूंगा कि संक्षेप में, CGLIB या Javassist के साथ किसी अन्य विधि के भीतर एक विधि कॉल को इंटरसेप्ट करना आसान है जो अवरोधन करने के लिए कहे, "यदि" ऑपरेटर।
Infeligo

मैंने अभी तक यहां अपने विवरण की मालिश नहीं की है, लेकिन मैं इसके बारे में भूल नहीं पाया हूं। FYI करें।
पॉल मोरी

33

संक्षिप्त उत्तर है, पर्दे के पीछे, मॉकिटो कुछ प्रकार के वैश्विक चर / भंडारण का उपयोग करता है ताकि विधि स्टब बिल्डिंग चरणों की जानकारी (विधि का आह्वान,), जब (), फिर (उदाहरण में आपके) में बचाया जा सके, ताकि अंततः यह हो सके क्या परम पर क्या कहा जाता है जब वापस आ जाना चाहिए पर एक नक्शा बनाएँ।

मुझे यह लेख बहुत उपयोगी लगा: व्याख्या कि प्रॉक्सी आधारित मॉक फ्रेमवर्क कैसे काम करता है ( http://blog.rseiler.at/2014/06/explanation-how-proxy-based-mock.html )। लेखक ने एक प्रदर्शन Mocking ढांचे को लागू किया, जो मुझे उन लोगों के लिए एक बहुत अच्छा संसाधन मिला, जो यह पता लगाना चाहते हैं कि ये Mocking रूपरेखा कैसे काम करती है।

मेरी राय में, यह एंटी-पैटर्न का एक विशिष्ट उपयोग है। आम तौर पर हमें एक विधि को लागू करने से 'दुष्प्रभाव' से बचना चाहिए, जिसका अर्थ है कि विधि को इनपुट स्वीकार करना चाहिए और कुछ गणना करनी चाहिए और परिणाम वापस करना चाहिए - इसके अलावा और कुछ नहीं बदला। लेकिन मॉकिटो सिर्फ उद्देश्य पर उस नियम का उल्लंघन करता है। इसके तरीके परिणाम को वापस करने के अलावा जानकारी का एक गुच्छा संग्रहीत करते हैं: Mockito.anyString (), mockInstance.method (), जब (), फिर, पुन: इन सभी का विशेष 'साइड इफेक्ट' होता है। यही कारण है कि पहली नज़र में फ्रेमवर्क एक जादू की तरह दिखता है - हम आमतौर पर उस तरह का कोड नहीं लिखते हैं। हालांकि, मॉकिंग फ्रेमवर्क मामले में, यह एंटी-पैटर्न डिजाइन एक महान डिजाइन है, क्योंकि यह बहुत सरल एपीआई की ओर जाता है।


4
बहुत बढ़िया लिंक। इसके पीछे की प्रतिभा यह है: बहुत ही सरल एपीआई जो पूरी चीज़ को बहुत अच्छी लगती है। एक और महान निर्णय यह है कि जब () विधि जेनेरिक का उपयोग करती है ताकि तत्पश्चात () विधि सुरक्षित हो।
डेविड टोनहोफर 22

मैं इसे बेहतर जवाब मानता हूं। अन्य उत्तर के विपरीत, यह स्पष्ट रूप से कंक्रीट कोड के माध्यम से नियंत्रण प्रवाह के बजाय मॉकिंग प्रक्रिया की अवधारणाओं को स्पष्ट करता है। मैं सहमत हूं, उत्कृष्ट लिंक।
मिहका
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.