Mockito स्थैतिक तरीकों का मजाक क्यों नहीं उड़ाता है?


267

मैंने स्टैटिक विधियों के बारे में यहाँ कुछ सूत्र पढ़े हैं, और मुझे लगता है कि मैं समझता हूँ कि समस्याओं का दुरुपयोग / स्टैटिक विधियों के अत्यधिक उपयोग के कारण हो सकते हैं। लेकिन मैं वास्तव में इस बात की तह तक नहीं गया कि स्थैतिक तरीकों का मजाक उड़ाना कठिन क्यों है।

मुझे पता है कि पॉवरमॉक की तरह अन्य मॉकिंग फ्रेमवर्क भी कर सकते हैं, लेकिन मॉकिटो क्यों नहीं कर सकते?

मैं इस लेख को पढ़ता हूं , लेकिन लेखक शब्द के खिलाफ धार्मिक रूप से लगता है static, शायद यह मेरी खराब समझ है।

एक आसान स्पष्टीकरण / लिंक बहुत अच्छा होगा।


12
बस एक साइड-नोट: पॉवरमॉक एक मॉक ऑब्जेक्ट लाइब्रेरी प्रति-से नहीं है, यह सिर्फ अन्य पुस्तकालयों के शीर्ष पर उन विशेषताओं (स्टैटिक्स और सीकर्स को मॉक करना) को जोड़ता है। हम पॉवरमॉक + मॉकिटो का उपयोग उस कार्य में करते हैं जो वे एक दूसरे के साथ अच्छी तरह से तैरते हैं।
मथियास

जवाबों:


238

मुझे लगता है कि इसका कारण यह हो सकता है कि नकली वस्तु पुस्तकालय आमतौर पर गतिशील रूप से रनटाइम पर कक्षाएं बनाकर ( cglib का उपयोग करके ) नकली बनाते हैं । इसका मतलब यह है कि वे या तो रनटाइम पर एक इंटरफ़ेस लागू करते हैं (कि ईज़ीमॉक अगर मैं गलत नहीं हूँ तो वह क्या करता है), या उन्हें क्लास से मॉकिट करने के लिए इनहेरिट किया जाता है (अगर मैं गलत नहीं हूँ तो मॉकिटो करता है)। दोनों दृष्टिकोण स्थिर सदस्यों के लिए काम नहीं करते हैं, क्योंकि आप इनहेरिटेंस का उपयोग करके उन्हें ओवरराइड नहीं कर सकते हैं।

स्टैटिक्स को मॉक करने का एकमात्र तरीका रनटाइम के समय एक क्लास बाइट कोड को संशोधित करना है, जो मुझे लगता है कि विरासत से थोड़ा अधिक शामिल है।

इसके लिए मेरा अनुमान है, इसके लायक क्या है ...


7
वैसे ही निर्माण करने वालों का मज़ाक उड़ाने के लिए भी यही सच है। वे भी विरासत के माध्यम से नहीं बदला जा सकता है।
मथायस

11
यह जोड़ने के लायक भी हो सकता है कि कुछ TDD / TBD प्रस्तावक स्थैतिक विधि की कमी और निर्माणकर्ता को एक अच्छी बात मानते हैं । उनका तर्क है कि जब आप खुद को स्थैतिक तरीकों या रचनाकारों का मजाक उड़ाते हुए पाते हैं, तो यह खराब वर्ग डिजाइन के लिए एक संकेतक है। उदाहरण के लिए, जब आपके कोड मॉड्यूल को इकट्ठा करने में एक शुद्ध IoC दृष्टिकोण का अनुसरण किया जाता है, तो आपको पहली बार में स्टैटिक्स या सीटर को मॉक करने की आवश्यकता नहीं होगी (जब तक कि वे निश्चित रूप से कुछ ब्लैक बॉक्स घटक का हिस्सा न हों)। यह भी देखें giorgiosironi.blogspot.com/2009/11/…
Matthias

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

11
@ लो-टैन - यह कहने जैसा है कि एक भाषा को हर चीज में सक्षम होना चाहिए, यह न मानते हुए कि वह आपसे बेहतर जानता है। यह सिर्फ आपकी ओर से घमंड है, क्योंकि वे थोपने के रूप में सामने आते हैं। यहां समस्या यह है कि "विरोधी / समर्थक स्थैतिक" लड़ाई स्पष्ट नहीं है, और इसलिए रूपरेखाएं हैं। मैं सहमत हूं कि हम दोनों के पास होना चाहिए। लेकिन जहां तथ्यों हैं स्पष्ट है, मैं एक रूपरेखा जो पसंद करते हैं लगाता उन तथ्यों। यह सीखने का एक तरीका है - आपको ट्रैक पर रखने वाले उपकरण। तो आप अपने आप को नहीं है। लेकिन अब हर नूडल सिर उनके तथाकथित "अच्छे डिजाइन" को लगा सकता है। "मौलिक रूप से त्रुटिपूर्ण" ...
nevvermind

13
@nevvermind एह? एक उच्च स्तरीय भाषा आपकी सहायता के लिए है और इसमें आवश्यक सार हैं ताकि आप महत्वपूर्ण टुकड़ों पर ध्यान केंद्रित कर सकें। एक परीक्षण पुस्तकालय एक उपकरण है - एक उपकरण जिसका उपयोग मैं बेहतर गुणवत्ता का उत्पादन करने के लिए करता हूं, और उम्मीद है कि बेहतर डिजाइन, कोड। परीक्षण / नकली लाइब्रेरी का क्या मतलब है जब इसकी सीमाएँ होती हैं जिसका मतलब यह हो सकता है कि मैं इसका उपयोग तब नहीं कर सकता जब मुझे किसी और के खराब डिज़ाइन कोड को एकीकृत करने की आवश्यकता हो? अच्छी तरह से सोचा नहीं लगता है, जबकि, अच्छी भाषाएँ रही हैं
लो-टैन

28

यदि आपको एक स्थिर विधि का मजाक उड़ाने की आवश्यकता है, तो यह खराब डिजाइन के लिए एक मजबूत संकेतक है। आमतौर पर, आप अपने क्लास-अंडर-टेस्ट की निर्भरता का मजाक उड़ाते हैं। यदि आपका क्लास-अंडर-टेस्ट एक स्थिर विधि को संदर्भित करता है - जैसे java.util.Math # sin for example - इसका मतलब है कि क्लास-अंडर-टेस्ट को वास्तव में इस कार्यान्वयन की आवश्यकता है (उदाहरण के लिए सटीकता बनाम गति)। यदि आप एक ठोस साइनस कार्यान्वयन से अमूर्त करना चाहते हैं, तो आपको शायद एक इंटरफ़ेस की आवश्यकता है (आप देखें कि यह कहां जा रहा है)?


3
खैर, मैंने उच्च-स्तरीय अमूर्तता प्रदान करने के लिए स्थैतिक तरीकों का उपयोग किया, जैसे कि "स्थिर दृढ़ता मुखौटा"। इस तरह का एक पहलू ओआरएम एपीआई की जटिलताओं और निम्न-स्तरीय विवरणों से क्लाइंट कोड को दूर रखता है, जिससे बहुत अधिक लचीलेपन की अनुमति देते हुए एपीआई का अधिक सुसंगत और आसान उपयोग होता है।
रोजरियो

और आपको इसका मजाक क्यों उड़ाना है? यदि आप स्थैतिक विधि पर निर्भर करते हैं, तो आप "इकाई" या "मॉड्यूल" अकेले वर्ग नहीं हैं, बल्कि "स्थैतिक दृढ़ता संकाय" भी शामिल हैं।
जन

88
यह सच है, लेकिन कभी-कभी आपके पास कोई विकल्प नहीं हो सकता है यदि उदाहरण के लिए आपको एक स्थिर विधि का मजाक उड़ाने की जरूरत है जो कि किसी तीसरे पक्ष के वर्ग में है।
स्टिजेन ज्युकेंस

6
सच है, लेकिन कभी-कभी हम एकल से निपट सकते हैं।
मनु मंजूनाथ

केवल ऐसा लगता है कि अमूर्त द्वारा हल नहीं किया जा सकता है अमूर्तता के कई स्तर हैं ... अमूर्त परतों को जोड़ना जटिलता जोड़ता है, और अक्सर अनावश्यक होता है। मुझे लगता है कि मैंने उन रूपरेखाओं के बारे में सोचा है जो इस सरल कॉल को एक ही वर्ग में लपेटकर System.currentTimeMillis () को मॉक करने की कोशिश करते हैं। हम केवल परीक्षण करने की सुविधा के लिए - केवल पद्धति के बजाय प्रति एकल वर्ग वर्ग के साथ समाप्त होते हैं। और फिर जब आप एक 3-पार्टी डिपो शुरू करते हैं जो आपके सिंगलटन रैपर के माध्यम से स्टैटिक विधि को सीधे कॉल करता है, तो परीक्षण वैसे भी विफल हो जाते हैं ...
Fr Jeremy Krieg

5

मैं गंभीरता से लगता है कि यह कोड गंध है अगर आप स्थैतिक तरीकों का मजाक उड़ाने की जरूरत है।

  • सामान्य कार्यक्षमता तक पहुँचने के लिए स्थैतिक तरीके? -> एक सिंगलटन उदाहरण का उपयोग करें और इसे इंजेक्ट करें
  • थर्ड पार्टी कोड? -> इसे अपने स्वयं के इंटरफ़ेस / प्रतिनिधि में लपेटें (और यदि आवश्यक हो तो इसे एक सिंगलटन भी बनाएं)

केवल एक बार यह मेरे लिए overkill लगता है, अमरूद की तरह libs है, लेकिन आप वैसे भी इस तरह का मजाक उड़ाने की जरूरत नहीं होनी चाहिए क्योंकि यह तर्क का हिस्सा है ... (Iterables.transform (..) की तरह सामान)
अपने खुद के कोड साफ-सुथरा रहता है, आप अपनी सभी निर्भरताओं को एक स्वच्छ तरीके से समाप्त कर सकते हैं, और आपके पास बाहरी निर्भरता के खिलाफ एक भ्रष्टाचार विरोधी परत है। मैंने पॉवरमॉक को व्यवहार में देखा है और इसके लिए हमारी जरूरत की सभी कक्षाओं को खराब तरीके से डिजाइन किया गया था। कई बार पॉवरमॉक के एकीकरण के कारण गंभीर समस्याएँ पैदा हुई
(जैसे https://code.google.com/p/powermock/issues/detail?id=355 )

पुनश्च: निजी विधियों के लिए भी समान है। मुझे नहीं लगता कि परीक्षणों को निजी तरीकों के विवरण के बारे में जानना चाहिए। यदि कोई वर्ग इतना जटिल है कि वह निजी तरीकों का मजाक उड़ाता है, तो यह संभवतः उस वर्ग को विभाजित करने का संकेत है ...


2
सिंगलटन आपको सभी प्रकार की समस्याओं में भाग देगा, खासकर जब आपको एहसास होगा कि आपको वास्तव में एक से अधिक उदाहरणों की आवश्यकता है और अब आपको ऐसा करने के लिए अपने पूरे सिस्टम को फिर से बनाने की आवश्यकता है।
रिकार्डो फ्रीटस

मैंने यह नहीं कहा, कि मैं सभी को सिंगलटन पैटर्न की सलाह देता हूं। मेरा क्या मतलब है, अगर मुझे एक स्थिर उपयोगिता वर्ग और एक ही कार्यक्षमता प्रदान करने वाले एक सिंगलटन के बीच फैसला करना है, तो मैं सिंगलटन चुनूंगा। और अगर एक वर्ग एक सिंगलटन है या नहीं वैसे भी डीआई फ्रेमवर्क द्वारा नियंत्रित किया जाना चाहिए, मेरी कक्षा में @Inject SomeDependencyऔर मेरे कॉन्फ़िगरेशन में मैं परिभाषित करता हूं bind(SomeDependency.class).in(Singleton.class)। इस प्रकार यदि कल यह एक सिंगलटन नहीं है, तो मैं एक कॉन्फिग को बदल देता हूं और वह यह है।
पेटे83

@ pete83 मैं आपको सुनता हूं भाई। हालाँकि, मेरे पास परीक्षण शुल्क या रूपरेखा के साथ एक मुद्दा है जो परीक्षण ढांचे के डिजाइन / सीमाओं को पूरा करने के लिए अपने डिजाइन को बदलने के लिए देवों की आवश्यकता होती है। वह IMO गाड़ी को घोड़े के आगे रख रहा है, या पूंछ कुत्ते को छेड़ रहा है।
मैट कैंपबेल

1
वह तर्क मेरे लिए बहुत मायने रखता है। यहाँ सूचीबद्ध करने के लिए बहुत सारे कारणों से, अब कुछ वर्षों से सिंगलटन पैटर्न अनुकूल हो गया है। "स्वच्छ" कोड क्या बनता है? यदि मेरे पास एक श्रेणी उदाहरण विधि है जो एक स्थिर सहायक विधि को कॉल करती है जो कुछ I / O ऑपरेशन लौटाती है, तो मैं क्यों नहीं चाहूंगा कि परीक्षण में इसका मजाक उड़ाया जाए? और वह ख़राब डिज़ाइन कैसा है? यह सब हाथ से लिखी हुई आस-पास की स्थैतिक विधियों का मजाक नहीं उड़ाता है। एक विधि का मजाक उड़ाना इसके परीक्षण के विपरीत है। अगर इसे लागू करना बहुत कठिन है, तो बस इतना ही कहिए और इसके साथ हो
जाइए

अरे यार, मैं उस पुराने स्कूल सिंगलटन पैटर्न के बारे में कभी नहीं बात कर रहा था, जहां हर कोई Foo.getInstance()हर जगह कहता है। मैंने केवल तर्क का जवाब देने के लिए सिंगलटन लिखा था "लेकिन एक स्थिर पद्धति को कई आवरण वस्तुओं के निर्माण की आवश्यकता नहीं है"। मेरे लिए वैचारिक रूप से एक स्थिर पद्धति और एक सिंगलटन पर एक उदाहरण विधि के बीच बहुत कम अंतर है, बस आप इस एकल सहयोगी का मजाक नहीं उड़ा सकते। लेकिन सिंगलटन पूरी तरह से वह बिंदु नहीं है जिसे मैं बनाने की कोशिश कर रहा था, यह बिंदु इंजेक्ट करने और मॉक सहयोगी बनाने के लिए है और स्थैतिक तरीकों को कॉल नहीं करना है अगर यह कठिन परीक्षण करता है।
पेटे83

4

मॉकिटो वस्तुओं को लौटाता है लेकिन स्थिर का अर्थ है "वर्ग स्तर, वस्तु स्तर नहीं" इसलिए मॉकिटो स्थैतिक के लिए अशक्त सूचक अपवाद देगा।


0

कुछ मामलों में, स्थैतिक तरीकों का परीक्षण करना मुश्किल हो सकता है, खासकर अगर उन्हें मज़ाक करने की आवश्यकता होती है, यही वजह है कि अधिकांश मॉकिंग फ्रेमवर्क उनका समर्थन नहीं करते हैं। स्टैटिक मेथड्स और क्लासेस को मॉक करने के तरीके के निर्धारण में मुझे यह ब्लॉग पोस्ट बहुत उपयोगी लगी।


1
एक उपयुक्त नकली एपीआई का उपयोग करते समय स्थैतिक विधियों का मजाक उड़ाना आसान है।
रोजरियो

यह प्रश्न के साथ प्रश्न का उत्तर देने जैसा है, यही कारण है कि ऐसा करना मुश्किल था, जिसके लिए यह उत्तर नहीं है।
मथियास

40
मैंने इसे डाउनवोट किया क्योंकि ब्लॉग पोस्ट वास्तव में उपयोग करने के लिए होने वाले स्थिर तरीकों से एक वर्ग को अलग करने के मुद्दे को हल करने के बजाय एक महंगा वर्कअराउंड (उत्पादन कोड को रिफलेक्ट करने) की सिफारिश करता है। IMO, एक मज़ाक करने वाला उपकरण जो वास्तव में काम करता है वह किसी भी प्रकार के तरीकों से भेदभाव नहीं करेगा; एक डेवलपर को यह तय करने के लिए स्वतंत्र होना चाहिए कि किसी दिए गए स्थान में स्थिर तरीकों का उपयोग अच्छा है या बुरा है, बजाय इसके कि किसी एक रास्ते को मजबूर किया जाए।
रोजेरियो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.