सवाल मैं निजी फ़ंक्शन या क्लास का परीक्षण कैसे करूं जिसमें निजी विधियां, फ़ील्ड या आंतरिक कक्षाएं हों?


मैं यूनिट टेस्ट (xUnit का उपयोग करके) एक कक्षा जिसमें आंतरिक निजी विधियों, फ़ील्ड या नेस्टेड कक्षाएं हैं? या एक समारोह जो निजी द्वारा किया जाता है आंतरिक जुड़ाव (static सी / सी ++ में) या एक निजी में है (गुमनाम) नामस्थान?

परीक्षण चलाने में सक्षम होने के लिए किसी विधि या फ़ंक्शन के लिए एक्सेस संशोधक को बदलने में बुरा लगता है।


2268


मूल


एक निजी विधि का परीक्षण करने का सबसे अच्छा तरीका यह सीधे परीक्षण नहीं कर रहा है - Surya
लेख की जांच करें JUnit और SuiteRunner के साथ निजी तरीके का परीक्षण। - Mouna Cheikhna
मैं असहमत हूं। ए (सार्वजनिक) विधि जो समझने में लंबा या मुश्किल है उसे दोबारा किया जाना चाहिए। यह मूर्खतापूर्ण होगा कि आप केवल सार्वजनिक के बजाय प्राप्त छोटी (निजी) विधियों का परीक्षण न करें। - Michael Piefel
किसी भी तरीके का परीक्षण नहीं करना क्योंकि यह दृश्यता बेवकूफ है। यहां तक ​​कि इकाई परीक्षण कोड के सबसे छोटे टुकड़े के बारे में होना चाहिए, और यदि आप केवल सार्वजनिक तरीकों का परीक्षण करते हैं तो आप कभी भी यह सुनिश्चित नहीं करेंगे कि त्रुटि कहां होती है - वह विधि, या कुछ अन्य। - Dainius
आपको कक्षा का परीक्षण करने की आवश्यकता है कार्यक्षमतानहीं, इसकी नहीं कार्यान्वयन। निजी तरीकों का परीक्षण करना चाहते हैं? उन्हें बुलाए जाने वाले सार्वजनिक तरीकों का परीक्षण करें। यदि श्रेणी की कार्यक्षमता पूरी तरह से परीक्षण की जाती है, तो इसके आंतरिक भाग सही और भरोसेमंद साबित हुए हैं; आपको आंतरिक परिस्थितियों का परीक्षण करने की आवश्यकता नहीं है। परीक्षण परीक्षण कक्षाओं से decoupling बनाए रखना चाहिए। - Calimar41


जवाब:


यदि आपके पास कुछ विरासत है जावा आवेदन, और आपको अपनी विधियों की दृश्यता बदलने की अनुमति नहीं है, निजी तरीकों का परीक्षण करने का सबसे अच्छा तरीका उपयोग करना है प्रतिबिंब

आंतरिक रूप से हम मदद / सेट करने के लिए मददगार का उपयोग कर रहे हैं private तथा private static चर के साथ ही आह्वान private तथा private static तरीकों। निम्नलिखित पैटर्न आपको निजी तरीकों और क्षेत्रों से संबंधित कुछ भी करने देंगे। बेशक आप नहीं बदल सकते हैं private static final प्रतिबिंब के माध्यम से चर।

Method method = targetClass.getDeclaredMethod(methodName, argClasses);
method.setAccessible(true);
return method.invoke(targetObject, argObjects);

और खेतों के लिए:

Field field = targetClass.getDeclaredField(fieldName);
field.setAccessible(true);
field.set(object, value);

टिप्पणियाँ:
  1। targetClass.getDeclaredMethod(methodName, argClasses) आपको देखने देता है private तरीकों। वही बात के लिए लागू होता है    getDeclaredField
  2. द setAccessible(true) निजी के साथ खेलने के लिए आवश्यक है।


1417



उपयोगी अगर आप शायद एपीआई नहीं जानते हैं, लेकिन यदि आपको इस तरीके से निजी तरीकों का परीक्षण करना पड़ रहा है तो आपके डिजाइन के साथ कुछ है। जैसा कि एक अन्य पोस्टर का कहना है कि इकाई परीक्षण कक्षा के अनुबंध का परीक्षण करना चाहिए: यदि अनुबंध बहुत व्यापक है और सिस्टम का बहुत अधिक तत्काल है तो डिजाइन को संबोधित किया जाना चाहिए। - andygavin
बहुत उपयोगी। इसका उपयोग करना यह ध्यान में रखना महत्वपूर्ण है कि परीक्षण खराब होने पर परीक्षण खराब हो जाएंगे। - Rick Minerich
उदाहरण कोड मेरे लिए काम नहीं करता था, लेकिन यह थिग स्पष्ट बनाता है: java2s.com/Tutorial/Java/0125__Reflection/... - Rob
प्रतिबिंब का उपयोग करने से काफी बेहतर होगा इसके लिए कुछ लाइब्रेरी का उपयोग करना होगा Powermock। - Michael Piefel
यही कारण है कि टेस्ट संचालित डिजाइन सहायक है। इससे आपको व्यवहार को सत्यापित करने के लिए क्या पता लगाना चाहिए, यह जानने में सहायता मिलती है। - Thorbjørn Ravn Andersen


एक निजी विधि का परीक्षण करने का सबसे अच्छा तरीका एक और सार्वजनिक विधि के माध्यम से है। यदि यह नहीं किया जा सकता है, तो निम्न स्थितियों में से एक सत्य है:

  1. निजी विधि मृत कोड है
  2. उस कक्षा के पास एक डिज़ाइन गंध है जिसका आप परीक्षण कर रहे हैं
  3. जिस विधि को आप परीक्षण करने का प्रयास कर रहे हैं वह निजी नहीं होना चाहिए

507



सहमत नहीं हैं। यह एक निजी विधि में एल्गोरिदम होना पूरी तरह से मान्य है जिसके लिए कक्षा के सार्वजनिक इंटरफेस के माध्यम से व्यावहारिक की तुलना में अधिक इकाई परीक्षण की आवश्यकता होती है। - Mr. Shiny and New 安宇
अरे श्री चमकदार हाँ, लेकिन फिर आप भंगुर परीक्षण करेंगे। इसके अलावा, मेरे उत्तर में नंबर 2 देखें। - Trumpi
एक भंगुर परीक्षण एक परीक्षण है जो कोड में बदलाव होने पर बहुत आसानी से विफल रहता है। आम तौर पर ऐसा तब होता है जब परीक्षण परिणाम अपेक्षित आउटपुट और इनपुट के सेट के साइड इफेक्ट्स के बजाय विधि के आधार पर क्या होता है, इस पर आधारित होता है। आदर्श रूप से, कोड में परिवर्तन जो परिणामों को नहीं बदलता है, परीक्षण को तोड़ना नहीं चाहिए। - aro_biz
@श्री। चमकदार और नया: यदि आपकी निजी विधि स्वतंत्र इकाई परीक्षण की गारंटी देने के लिए पर्याप्त जटिल है, तो यह अपनी कक्षा के लिए पर्याप्त जटिल है। कक्षा निश्चित रूप से आंतरिक हो सकती है (यानी अन्य पैकेजों से सुलभ नहीं है)। - sleske
@sleske, मैं सहमत नहीं हूँ। आपके पास एक छोटी निजी विधि हो सकती है जिसे डिजाइन द्वारा आपको निजी होने की आवश्यकता होती है। और मैं जनता के माध्यम से निजी विधि का परीक्षण करने के बजाय कोड के प्रत्येक छोटे टुकड़े का परीक्षण करूंगा। परीक्षण का यह तरीका एक घटक परीक्षण की ओर जाएगा। - despot


जब मेरे पास ऐसी कक्षा में निजी तरीके हैं जो पर्याप्त जटिल हैं कि मुझे सीधे निजी तरीकों का परीक्षण करने की आवश्यकता महसूस होती है, तो यह एक कोड गंध है: मेरी कक्षा बहुत जटिल है।

इस तरह के मुद्दों को संबोधित करने के लिए मेरा सामान्य दृष्टिकोण दिलचस्प बिट्स वाली एक नई कक्षा को छेड़छाड़ करना है। अक्सर, इस विधि और फ़ील्ड के साथ यह बातचीत करता है, और शायद एक और विधि या दो को एक नई कक्षा में निकाला जा सकता है।

नई कक्षा इन विधियों को 'सार्वजनिक' के रूप में उजागर करती है, इसलिए वे इकाई परीक्षण के लिए पहुंच योग्य हैं। नई और पुरानी कक्षाएं अब मूल वर्ग की तुलना में सरल हैं, जो मेरे लिए बहुत अच्छी है (मुझे चीजों को सरल रखना है, या मैं खो गया हूं!)।

ध्यान दें कि मैं यह सुझाव नहीं दे रहा हूं कि लोग अपने दिमाग का उपयोग किए बिना कक्षाएं बनाते हैं! यहां बिंदु यह है कि आपको अच्छी नई कक्षाएं खोजने में मदद के लिए यूनिट परीक्षण की ताकतों का उपयोग करना है।


272



प्रश्न निजी तरीकों का परीक्षण कैसे किया गया था। आप कहते हैं कि आप इसके लिए नई कक्षा (और अधिक जटिलता जोड़ें) करेंगे और नई कक्षा बनाने के सुझाव देने के बाद। तो निजी तरीकों का परीक्षण कैसे करें? - Dainius
मुझे लगता है कि यदि आपके पास विधि है तो उस विधि का परीक्षण करने में सक्षम होने के लिए किसी अन्य वर्ग को बनाने की आवश्यकता नहीं है। मुझे नहीं लगता कि क्लास डिज़ाइन यहां सवाल था .. इसलिए मुझे लगता है कि लेखक ने सबकुछ उचित डिजाइन करने के लिए किया था, इसलिए एक विधि के लिए एक और कक्षा शुरू करना जो आप जटिलता को बढ़ा रहे हैं। बेशक जब आपके पास पर्याप्त जटिल कार्यक्रम है, तो कोई स्पष्ट बग नहीं होगा .. - Dainius
@ डेनियस: मैं एक नई कक्षा बनाने का सुझाव नहीं देता हूं केवल तो आप उस विधि का परीक्षण कर सकते हैं। मेरा सुझाव है कि लेखन परीक्षण आपको अपने डिजाइन को बेहतर बनाने में मदद कर सकते हैं: अच्छे डिज़ाइन परीक्षण करना आसान है। - Jay Bazuzi
लेकिन आप सहमत हैं कि अच्छा ओओडी उस वर्ग / ऑब्जेक्ट के लिए सही तरीके से काम करने के लिए आवश्यक विधियों का खुलासा करेगा (सार्वजनिक करें)? अन्य सभी निजी / संरक्षित होना चाहिए। इसलिए कुछ निजी तरीकों में कुछ तर्क होंगे, और आईएमओ इन तरीकों का परीक्षण केवल सॉफ्टवेयर की गुणवत्ता में सुधार करेगा। बेशक मैं सहमत हूं कि यदि कोड का कुछ टुकड़ा जटिल है तो इसे अलग-अलग तरीकों / वर्ग में विभाजित किया जाना चाहिए। - Dainius
@ डैनियस: ज्यादातर मामलों में, एक नई कक्षा जोड़ना जटिलता को कम करता है। बस इसे मापो। कुछ मामलों में टेस्टेबिलिटी ओओडी के खिलाफ झगड़ा करता है। आधुनिक दृष्टिकोण अनुकूलता का पक्ष है। - AlexWien


मैंने उपयोग कर लिया है प्रतिबिंब अतीत में जावा के लिए ऐसा करने के लिए, और मेरी राय में यह एक बड़ी गलती थी।

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

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


229



इसे +1 करें। मेरी राय में यह सवाल का सबसे अच्छा जवाब है। निजी तरीकों का परीक्षण करके आप कार्यान्वयन का परीक्षण कर रहे हैं। यह यूनिट परीक्षण के उद्देश्य को हरा देता है, जो कक्षा के अनुबंध के इनपुट / आउटपुट का परीक्षण करना है। एक परीक्षण चाहिए केवल अपनी निर्भरताओं पर कॉल की जाने वाली विधियों को नकल करने के लिए कार्यान्वयन के बारे में पर्याप्त जानकारी प्राप्त करें। और कुछ नहीं। यदि आप परीक्षण को बदलने के बिना अपना कार्यान्वयन नहीं बदल सकते हैं - संभावना है कि आपकी परीक्षण रणनीति खराब है। - Colin M
@ कोलिन एम यह वास्तव में वह नहीं है जो वह पूछ रहा है;) उसे निर्णय लेने दो, आप इस परियोजना को नहीं जानते हैं। - Aaron Marcus
वास्तव में सच नहीं है। यह सार्वजनिक विधि के माध्यम से निजी विधि के एक छोटे से हिस्से का परीक्षण करने के लिए बहुत प्रयास कर सकता है। आपकी निजी विधि को कॉल करने वाली लाइन तक पहुंचने से पहले सार्वजनिक विधि को महत्वपूर्ण सेटअप की आवश्यकता हो सकती है - ACV


इस लेख से: JUnit और SuiteRunner के साथ निजी तरीके का परीक्षण (बिल वेनेर्स), आपके मूल रूप से 4 विकल्प हैं:

  • निजी तरीकों का परीक्षण न करें।
  • विधियों के पैकेज की अनुमति दें।
  • एक नेस्टेड टेस्ट क्लास का प्रयोग करें।
  • प्रतिबिंब का प्रयोग करें।

187



@ user86614 उत्पादन कोड में टेस्ट कोड डालना एक अच्छा विचार नहीं है। - Jimmy T.
@ जिमीमी।, इस पर निर्भर करता है कि "उत्पादन कोड" किसके लिए है। मैं वीपीएन के भीतर स्थित अनुप्रयोगों के लिए उत्पादित कोड कॉल करूंगा जिसका लक्षित उपयोगकर्ता सिसडमिन उत्पादन कोड होने के लिए हैं। - Pacerier
@Pacerier आपका क्या मतलब है? - Jimmy T.
उपरोक्त वर्णित 5 वां विकल्प सार्वजनिक विधि का परीक्षण कर रहा है जो निजी विधि कहता है? सही बात? - user2441441
@LorenzoLerate मैं इसके साथ कुश्ती कर रहा हूं क्योंकि मैं एम्बेडेड विकास कर रहा हूं और मैं चाहता हूं कि मेरा सॉफ़्टवेयर जितना संभव हो उतना छोटा हो। आकार की बाधाएं और प्रदर्शन एकमात्र कारण है जिसके बारे में मैं सोच सकता हूं।


आम तौर पर एक इकाई परीक्षण का उद्देश्य कक्षा या इकाई के सार्वजनिक इंटरफ़ेस का उपयोग करना है। इसलिए, निजी विधियां कार्यान्वयन विस्तार हैं जिन्हें आप स्पष्ट रूप से परीक्षण करने की उम्मीद नहीं करेंगे।


96



यह आईएमओ का सबसे अच्छा जवाब है, या जैसा कि आमतौर पर कहा जाता है, परीक्षण व्यवहार, तरीकों से नहीं। यूनिट परीक्षण स्रोत कोड मीट्रिक, स्थिर कोड विश्लेषण उपकरण और कोड समीक्षाओं के प्रतिस्थापन नहीं है। यदि निजी विधियां इतनी जटिल हैं कि उन्हें परीक्षणों को अलग करने की आवश्यकता है तो संभवतः इसे फिर से संसाधित करने की आवश्यकता है, इस पर अधिक परीक्षण नहीं किए जाएंगे। - Dan Haynes
तो निजी तरीकों को मत लिखो, बस 10 अन्य छोटी कक्षाएं बनाएं? - razor


सिर्फ दो उदाहरण हैं जहां मैं एक निजी विधि का परीक्षण करना चाहता हूं:

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

मैं केवल "अनुबंध" का परीक्षण करने के विचार को समझता हूं। लेकिन मुझे नहीं लगता कि कोई वास्तव में कोड का परीक्षण नहीं कर सकता है - आपका माइलेज भिन्न हो सकता है।

तो मेरे व्यापार में मेरी सुरक्षा और एसडीके समझौता करने के बजाय, ज्यूनिट्स को प्रतिबिंब के साथ जटिल बनाना शामिल है।


56



जबकि आपको इसका परीक्षण करने के लिए कभी भी एक विधि सार्वजनिक नहीं करना चाहिए, private एकमात्र विकल्प नहीं है। कोई एक्सेस संशोधक नहीं है package private और इसका मतलब यह है कि जब तक आपका यूनिट परीक्षण उसी पैकेज में रहता है तब तक आप इकाई का परीक्षण कर सकते हैं। - ngreen
@ngreen यह सब सच है, लेकिन सवाल यह नहीं है कि सवाल क्या है। ओपी निजी तरीकों का परीक्षण करने के बारे में पूछता है। डिफ़ॉल्ट निजी के समान नहीं है; जैसा कि कहा गया है, आप उसी वर्ग में उस वर्ग को घोषित करके कक्षा से डिफ़ॉल्ट पहुंच विधि आसानी से देख सकते हैं। निजी पहुंच के साथ, आपको प्रतिबिंब की आवश्यकता होती है, जो एक संपूर्ण अन्य बॉलगेम है। - Richard Le Mesurier
मैं आपके उत्तर पर टिप्पणी कर रहा था, विशेष रूप से बिंदु 1, ओपी नहीं। विधि को निजी बनाने की कोई आवश्यकता नहीं है क्योंकि आप इसे सार्वजनिक नहीं करना चाहते हैं। - ngreen
@ngreen सच thx - मैं "सार्वजनिक" शब्द के साथ आलसी था। मैंने सार्वजनिक, संरक्षित, डिफ़ॉल्ट (और प्रतिबिंब का उल्लेख करने के लिए) को शामिल करने के लिए उत्तर अपडेट किया है। जिस बिंदु को मैं बनाने की कोशिश कर रहा था वह यह है कि कुछ कोड गुप्त होने का एक अच्छा कारण है, हालांकि हमें इसे परीक्षण करने से नहीं रोकना चाहिए। - Richard Le Mesurier
सभी को असली उदाहरण देने के लिए धन्यवाद। अधिकांश उत्तर अच्छे होते हैं, लेकिन एक सैद्धांतिक दृष्टिकोण में। वास्तविक दुनिया में, हमें अनुबंध से कार्यान्वयन को छिपाने की आवश्यकता है, और हमें अभी भी इसका परीक्षण करने की आवश्यकता है। इन सभी को पढ़ना, मुझे लगता है कि शायद यह एक अलग नाम के साथ परीक्षण का एक नया स्तर होना चाहिए - Z. Khullah