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


2725

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

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


257
एक निजी विधि का परीक्षण करने का सबसे अच्छा तरीका सीधे इसका परीक्षण नहीं है
सूर्या


383
मैं असहमत हूं। एक (सार्वजनिक) विधि जो लंबे या कठिन को समझने के लिए फिर से तैयार की जानी है। यह केवल उन सार्वजनिक (निजी) तरीकों का परीक्षण नहीं करना होगा जो आपको केवल सार्वजनिक एक के बजाय मिलते हैं।
माइकल पिफेल

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

126
आपको क्लास की कार्यक्षमता का परीक्षण करने की आवश्यकता है , न कि इसके कार्यान्वयन की । निजी तरीकों का परीक्षण करना चाहते हैं? उन सार्वजनिक तरीकों का परीक्षण करें जो उन्हें कहते हैं। यदि कार्यक्षमता की पेशकश की गई कक्षा को अच्छी तरह से जांचा जाता है, तो इसके आंतरिक लोगों ने सही और विश्वसनीय होने का प्रदर्शन किया है; आपको आंतरिक स्थितियों का परीक्षण करने की आवश्यकता नहीं है। परीक्षणों में परीक्षण किए गए वर्गों से डिकॉउलिंग को बनाए रखना चाहिए।
कैलिमार 41

जवाबों:


1639

अपडेट करें:

कुछ 10 साल बाद का सबसे अच्छा तरीका एक निजी विधि, या किसी भी दुर्गम सदस्य परीक्षण करने के लिए शायद, के माध्यम से है @Jailbreakसे मैनिफोल्ड ढांचा।

@Jailbreak Foo foo = new Foo();
// Direct, *type-safe* access to *all* foo's members
foo.privateMethod(x, y, z);
foo.privateField = value;

इस तरह आपका कोड टाइप-सुरक्षित और पठनीय रहता है। कोई डिज़ाइन समझौता नहीं करता है, कोई अति-परीक्षण विधियों और परीक्षणों के लिए फ़ील्ड नहीं है।

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

आंतरिक रूप से हम मदद करने के लिए / सेट 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)निजी के साथ खेलने के लिए आवश्यक है।


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

21
बहुत उपयोगी। इसका उपयोग करते हुए यह ध्यान रखना महत्वपूर्ण है कि यदि परीक्षण स्थगित किए गए थे तो यह बुरी तरह से विफल हो जाएगा।
रिक मिनेरिच

20
उदाहरण कोड मेरे लिए काम नहीं करता था, लेकिन इससे थिग्स
Rob

35
सीधे प्रतिबिंब का उपयोग करने से बेहतर यह होगा कि इसके लिए कुछ लाइब्रेरी का उपयोग किया जाए जैसे कि पावरमॉक
माइकल पिफेल

25
यही कारण है कि टेस्ट ड्रिवन डिजाइन सहायक है। यह आपको यह पता लगाने में मदद करता है कि व्यवहार को मान्य करने के लिए किन चीजों को उजागर किया जाना चाहिए।
थोरबजोर्न रेवन एंडरसन

621

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

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

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

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

9
@AlexWien तुम सही हो। कवरेज सही शब्द नहीं था। मुझे क्या कहना चाहिए था "यदि आपके परीक्षण के वर्ग के अनुबंध सभी सार्थक इनपुट और सभी सार्थक राज्यों को कवर करते हैं"। यह, आप सही ढंग से इंगित करते हैं, सार्वजनिक इंटरफ़ेस के माध्यम से कोड के लिए परीक्षण करने के लिए, या अप्रत्यक्ष रूप से आपके द्वारा संदर्भित के रूप में परीक्षण करने योग्य साबित हो सकता है। अगर आपके द्वारा परीक्षण किए जा रहे कुछ कोड के लिए ऐसा है, तो मैं भी सोचना चाहूंगा: (1) अनुबंध बहुत उदार है (उदाहरण के लिए विधि में बहुत सारे पैरामीटर), या (2) अनुबंध बहुत अस्पष्ट है (जैसे विधि व्यवहार वर्ग राज्य के साथ बहुत भिन्न होता है)। मैं दोनों डिजाइन महक पर विचार करूंगा।
एरिक मैडसेन

16
लगभग सभी निजी तरीकों का सीधे परीक्षण नहीं किया जाना चाहिए (रखरखाव लागत कम करने के लिए)। अपवाद: वैज्ञानिक विधियों में f (a (b (c (x), d) (y)), (a (x, z)), b (f (x, y, z), z) जैसे रूप हो सकते हैं। जहां ए, बी, सी, डी, ई और एफ बुरी तरह से जटिल अभिव्यक्ति हैं लेकिन अन्यथा इस एकल सूत्र के बाहर बेकार हैं। कुछ फ़ंक्शंस (सोचिए एमडी 5) इनवर्टर के लिए कठिन हैं, इसलिए ऐसे मापदंडों (एनपी-हार्ड) को चुनना मुश्किल हो सकता है जो पूरी तरह से व्यवहार स्थान को कवर करेंगे। स्वतंत्र रूप से ए, बी, सी, डी, ई, एफ का परीक्षण करना आसान है। उन्हें सार्वजनिक या पैकेज-निजी झूठ बनाना कि वे पुन: प्रयोज्य हैं। समाधान: उन्हें निजी बनाएं, लेकिन उनका परीक्षण करें।
नामस्रोत

4
@ अनाम मैं इस पर थोड़ा फटा हुआ हूँ। मुझ में ऑब्जेक्ट ओरिएंटेड शुद्धतावादी कहेंगे कि आपको स्थिर निजी तरीकों के बजाय ऑब्जेक्ट ओरिएंटेड दृष्टिकोण का उपयोग करना चाहिए, जिससे आप सार्वजनिक उदाहरण विधियों के माध्यम से परीक्षण कर सकते हैं। लेकिन फिर से, एक वैज्ञानिक ढांचे में स्मृति ओवरहेड पूरी तरह से एक चिंता का विषय है जो मुझे विश्वास है कि स्थैतिक दृष्टिकोण के लिए तर्क है।
एरिक मैडसेन

323

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

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

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

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


24
सवाल था कि निजी तरीकों का परीक्षण कैसे किया जाए। आप कहते हैं कि आप उसके लिए नई कक्षा करेंगे (और बहुत अधिक जटिलता जोड़ेंगे) और उसके बाद नई कक्षा न बनाने का सुझाव देंगे। तो निजी तरीकों का परीक्षण कैसे करें?
Dainius

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

13
लेकिन आप इस बात से सहमत हैं कि अच्छा OOD सही तरीके से काम करने के लिए केवल उन तरीकों को उजागर करेगा (जो सार्वजनिक हो) उस वर्ग / वस्तु के लिए आवश्यक हैं? अन्य सभी निजी / सुरक्षित होना चाहिए। इसलिए कुछ निजी तरीकों में कुछ तर्क होंगे, और आईएमओ इन तरीकों का परीक्षण केवल सॉफ्टवेयर की गुणवत्ता में सुधार करेगा। बेशक, मैं मानता हूं कि यदि कुछ कोड जटिल है तो इसे अलग-अलग तरीकों / वर्ग में विभाजित किया जाना चाहिए।
Dainius

6
@ डैनियस: एक नया वर्ग जोड़ना, ज्यादातर मामलों में जटिलता को कम करता है। बस इसे मापें। कुछ मामलों में परीक्षण OOD के खिलाफ लड़ता है। आधुनिक दृष्टिकोण एहसानमंद है।
एलेक्सवियन

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

289

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

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

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


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

10
@Colin एम वह वास्तव में वह क्या पूछ रहा है नहीं है;) उसे यह फैसला करते हैं, आप इस परियोजना को नहीं जानते।
एरॉन मार्कस

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

1
मैं सहमत हूँ। यदि अनुबंध पूरा हो गया है, तो आपको परीक्षण करना चाहिए। आपको परीक्षण नहीं करना चाहिए, यह कैसे किया जाता है। यदि संपर्क 100% कोड कवरेज (निजी तरीकों में) तक पहुंचने के बिना पूरा होता है, तो वह मृत या बेकार कोड हो सकता है।
४३ पर i:

207

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

  1. निजी तरीकों का परीक्षण न करें।
  2. तरीकों पैकेज का उपयोग दे।
  3. नेस्टेड टेस्ट क्लास का उपयोग करें।
  4. प्रतिबिंब का उपयोग करें।

@JimmyT।, निर्भर करता है कि "उत्पादन कोड" किसके लिए है। मैं वीपीएन के भीतर तैनात अनुप्रयोगों के लिए निर्मित कोड को कॉल करूंगा, जिनके लक्षित उपयोगकर्ता उत्पादन कोड होने के लिए sysadmins हैं।
पचेरियर

@Pacerier तुम्हारा क्या मतलब है?
जिमी टी।

1
5 वां विकल्प, जैसा कि ऊपर उल्लेख किया गया है, सार्वजनिक विधि का परीक्षण कर रहा है जो निजी विधि को बुलाता है? सही बात?
user2441441

1
@LorenzoLerate मैं इसके साथ कुश्ती कर रहा हूं क्योंकि मैं एम्बेडेड विकास कर रहा हूं और मैं चाहता हूं कि मेरा सॉफ्टवेयर यथासंभव छोटा हो। आकार की कमी और प्रदर्शन ही एकमात्र कारण है जिसके बारे में मैं सोच सकता हूं।

मैं वास्तव में प्रतिबिंब का उपयोग करके परीक्षण पसंद करता हूं: यहां पैटर्न विधि विधि = targetClass.getDeclaredMethod (methodName, argClasses); method.setAccessible (सही); वापसी method.invoke (targetObject, argObjects);
एग्यूड

127

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


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

14
इसलिए निजी तरीके न लिखें, सिर्फ 10 अन्य छोटी कक्षाएं बनाएं?
रेजर

1
नहीं, इसका मूल रूप से यह मतलब है कि आप सार्वजनिक पद्धति का उपयोग करके निजी तरीकों की कार्यक्षमता का परीक्षण कर सकते हैं जो उन्हें आमंत्रित करता है।
अक्षत शारदा

66

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

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

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

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


5
जबकि आपको इसे परीक्षण करने के लिए कभी भी विधि को सार्वजनिक नहीं करना चाहिए, privateकेवल एकमात्र विकल्प नहीं है। कोई एक्सेस मॉडिफायर नहीं है package privateऔर इसका मतलब है कि जब तक आपका यूनिट टेस्ट एक ही पैकेज में रहता है, तब तक आप इसका परीक्षण कर सकते हैं।
एनग्रीन

1
मैं आपके जवाब पर टिप्पणी कर रहा था, विशेष रूप से अंक 1, ओपी नहीं। कोई विधि निजी बनाने की आवश्यकता नहीं है क्योंकि आप इसे सार्वजनिक नहीं करना चाहते हैं।
16

1
@ngreen सच thx - मैं "जनता" शब्द से आलसी था। मैंने सार्वजनिक, संरक्षित, डिफ़ॉल्ट (और प्रतिबिंब का उल्लेख करने के लिए) को शामिल करने के उत्तर को अपडेट किया है। मैं जिस बिंदु को बनाने की कोशिश कर रहा था, वह यह है कि कुछ कोड के गुप्त होने का अच्छा कारण है, हालांकि हमें इसे परीक्षण करने से नहीं रोकना चाहिए।
रिचर्ड ले मेसियर

2
सभी को वास्तविक उदाहरण देने के लिए धन्यवाद। अधिकांश उत्तर अच्छे हैं, लेकिन एक सैद्धांतिक दृष्टिकोण से। वास्तविक दुनिया में, हमें अनुबंध से कार्यान्वयन को छिपाने की आवश्यकता है, और हमें अभी भी इसका परीक्षण करने की आवश्यकता है। इन सभी को पढ़ते हुए, मुझे लगता है कि शायद यह एक अलग नाम के साथ परीक्षण का एक नया स्तर होना चाहिए
Z. खुल्ला

1
एक और उदाहरण - क्रॉलर HTML पार्सर । डोमेन ऑब्जेक्ट्स में पूरे HTML पृष्ठ को पार्स करने के लिए संरचना के छोटे भागों को मान्य करने के लिए एक टन के किटी-ग्रिट्टी तर्क की आवश्यकता होती है। यह समझ में आता है कि तरीकों को तोड़ना और इसे एक सार्वजनिक विधि से कॉल करना, फिर भी यह समझ में नहीं आता है कि सभी छोटे तरीकों की रचना यह सार्वजनिक है, और न ही यह प्रति HTML पृष्ठ पर 10 कक्षाएं बनाने के लिए बहुत मायने रखता है।
नीचे का

59

निजी तरीकों को एक सार्वजनिक विधि कहा जाता है, इसलिए आपके सार्वजनिक तरीकों के इनपुट को उन निजी तरीकों का भी परीक्षण करना चाहिए जिन्हें उन सार्वजनिक विधियों द्वारा कहा जाता है। जब कोई सार्वजनिक पद्धति विफल हो जाती है, तो वह निजी पद्धति में विफलता हो सकती है।


सही तथ्य। समस्या तब है जब कार्यान्वयन अधिक जटिल है, जैसे कि एक सार्वजनिक विधि कई निजी तरीकों को बुलाती है। कौन सा फेल हुआ? या अगर यह एक जटिल निजी तरीका है, जिसे उजागर नहीं किया जा सकता है और न ही एक नए वर्ग को हस्तांतरित किया जा सकता है
जेड। खुल्ला

आपने पहले ही उल्लेख किया है कि निजी पद्धति का परीक्षण क्यों किया जाना चाहिए। आपने कहा "फिर वह हो सकता है", इसलिए आपको यकीन नहीं है। IMO, एक विधि का परीक्षण किया जाना चाहिए या नहीं, इसके पहुँच स्तर तक ऑर्थोगोनल है।
वी किउ

39

एक और तरीका जो मैंने प्रयोग किया है वह है निजी या संरक्षित पैकेज को बदलने के लिए एक निजी तरीका बदलना और फिर इसे Google Guava लाइब्रेरी के @VoiceForTesting एनोटेशन के साथ पूरक करना ।

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

उदाहरण के लिए, यदि परीक्षण की जाने वाली एक विधि है, src/main/java/mypackage/MyClass.javaतो आपकी परीक्षण कॉल को अंदर रखा जाना चाहिए src/test/java/mypackage/MyClassTest.java। इस तरह, आपको अपने परीक्षण वर्ग में परीक्षण विधि तक पहुंच प्राप्त हुई।


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

2
मेरे लिए, यह आग ड्रिल का परीक्षण करने के लिए अपने फायर वार्डन को एक-बंद कुंजी देने के बजाय कहने जैसा है, आप अपने सामने के दरवाजे को दरवाजे पर एक संकेत के साथ खुला छोड़ते हुए कहते हैं - "परीक्षण के लिए खुला - अगर आप से नहीं हैं हमारी कंपनी, कृपया दर्ज न करें "।
फादर जेरेमी क्रिएग

@FrJeremyKrieg - इसका क्या मतलब है?
मास्टरजॉ

1
@ MasterJoe2: अग्नि परीक्षा का उद्देश्य आग के जोखिम के खिलाफ अपनी इमारत की सुरक्षा में सुधार करना है। लेकिन आपको वार्डन को अपनी इमारत तक पहुंच देनी होगी। यदि आप स्थायी रूप से सामने के दरवाजे को खुला छोड़ देते हैं, तो आप अनधिकृत पहुंच के जोखिम को बढ़ाते हैं और इसे कम सुरक्षित बनाते हैं। वही विज़िबलफ़ॉर्मिंग पैटर्न का सच है - आप "आग" के जोखिम को कम करने के लिए अनधिकृत पहुंच के जोखिम को बढ़ा रहे हैं। केवल परीक्षण के लिए एक बंद के रूप में पहुंच प्रदान करने के लिए बेहतर है जब आपको स्थायी रूप से अनलॉक किए गए (गैर-निजी) के बजाय (जैसे, प्रतिबिंब का उपयोग करके) की आवश्यकता होती है।
फ्रा जेरेमी क्रैग

34

बड़े और विचित्र वर्गों के साथ परीक्षण विरासत कोड के लिए, यह अक्सर बहुत एक निजी (या सार्वजनिक) विधि मैं लिख रहा हूँ परीक्षण करने के लिए सक्षम होने के लिए उपयोगी है अभी

मैं जावा के लिए junitx.util.PStreetAccessor -package का उपयोग करता हूं । निजी तरीकों और निजी क्षेत्रों तक पहुँचने के लिए मददगार एक-लाइनर्स।

import junitx.util.PrivateAccessor;

PrivateAccessor.setField(myObjectReference, "myCrucialButHardToReachPrivateField", myNewValue);
PrivateAccessor.invoke(myObjectReference, "privateMethodName", java.lang.Class[] parameterTypes, java.lang.Object[] args);

2
संपूर्ण JUnit-addons ( sourceforge.net/projects/junit-addons ) पैकेज को डाउनलोड करना सुनिश्चित करें , न कि स्रोत फोर्ज-अनुशंसित प्रोजेक्ट PrivateAccessor।
skia.heliou

2
और सुनिश्चित करें कि, जब आप Classइन विधियों में अपने पहले पैरामीटर के रूप में उपयोग कर रहे हैं, तो आप केवल staticसदस्यों तक ही पहुँच रहे हैं ।
skia.heliou

31

में स्प्रिंग फ्रेमवर्क आप निजी तरीकों इस पद्धति का उपयोग परीक्षण कर सकते हैं:

ReflectionTestUtils.invokeMethod()

उदाहरण के लिए:

ReflectionTestUtils.invokeMethod(TestClazz, "createTest", "input data");

सबसे साफ और सबसे संक्षिप्त समाधान अब तक, लेकिन केवल अगर आप स्प्रिंग का उपयोग कर रहे हैं।
डेनिस निकोलाेंको

28

जावा के लिए प्रतिबिंब का उपयोग करते हुए Cem Catikkas के समाधान की कोशिश करने के बाद , मुझे यह कहना पड़ेगा कि मैं यहाँ वर्णित की तुलना में अधिक सुरुचिपूर्ण समाधान था। हालांकि, यदि आप प्रतिबिंब का उपयोग करने के लिए एक विकल्प की तलाश कर रहे हैं, और आपके द्वारा परीक्षण किए जा रहे स्रोत तक पहुंच है, तो यह अभी भी एक विकल्प होगा।

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

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

लाभ:

  • एक बारीक बारीकियों का परीक्षण कर सकते हैं

नुकसान:

  • टेस्ट कोड को स्रोत कोड के समान फ़ाइल में रहना चाहिए, जिसे बनाए रखना अधिक कठिन हो सकता है
  • इसी तरह .class आउटपुट फाइलों के साथ, उन्हें उसी कोड के भीतर रहना चाहिए जैसा कि सोर्स कोड में घोषित किया गया है

हालांकि, यदि निरंतर परीक्षण के लिए इस पद्धति की आवश्यकता होती है, तो यह एक संकेत हो सकता है कि निजी तरीकों को निकाला जाना चाहिए, जो पारंपरिक, सार्वजनिक तरीके से परीक्षण किया जा सकता है।

यहाँ एक जटिल उदाहरण है कि यह कैसे काम करेगा:

// Import statements and package declarations

public class ClassToTest
{
    private int decrement(int toDecrement) {
        toDecrement--;
        return toDecrement;
    }

    // Constructor and the rest of the class

    public static class StaticInnerTest extends TestCase
    {
        public StaticInnerTest(){
            super();
        }

        public void testDecrement(){
            int number = 10;
            ClassToTest toTest= new ClassToTest();
            int decremented = toTest.decrement(number);
            assertEquals(9, decremented);
        }

        public static void main(String[] args) {
            junit.textui.TestRunner.run(StaticInnerTest.class);
        }
    }
}

भीतर के वर्ग को संकलित किया जाएगा ClassToTest$StaticInnerTest

इसे भी देखें: जावा टिप 106: मज़ेदार और लाभ के लिए स्टेटिक इनर क्लासेस


26

जैसा कि दूसरों ने कहा है ... सीधे निजी तरीकों का परीक्षण न करें। यहाँ कुछ विचार हैं:

  1. सभी तरीकों को छोटा और केंद्रित रखें (परीक्षण करना आसान है, जो गलत है उसे ढूंढना आसान है)
  2. कोड कवरेज टूल का उपयोग करें। मुझे कॉबर्टुरा पसंद है (ओह खुश दिन, ऐसा लगता है जैसे एक नया संस्करण बाहर है!)

इकाई परीक्षणों पर कोड कवरेज चलाएँ। यदि आप देखते हैं कि कवरेज प्राप्त करने के लिए तरीकों को पूरी तरह से परीक्षण में नहीं जोड़ा गया है। 100% कोड कवरेज के लिए निशाना लगाओ, लेकिन एहसास है कि तुम शायद यह नहीं मिलेगा।


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

मैंने उन कक्षाओं को देखा है जहां एकमात्र सार्वजनिक विधि मुख्य है [], और वे जीयूआई प्लस पॉप अप करते हैं और दुनिया भर में वेब सर्वरों के एक जोड़े को जोड़ते हैं। यह कहना आसान है "अप्रत्यक्ष रूप से परीक्षण न करें" ...
ऑड्रियस मेस्कॉस्कस

26

निजी तरीकों को सार्वजनिक लोगों द्वारा उपभोग किया जाता है। अन्यथा, वे मृत कोड हैं। इसीलिए आप सार्वजनिक पद्धति का परीक्षण करते हैं, सार्वजनिक पद्धति के अपेक्षित परिणामों का पता लगाते हैं और इस तरह, निजी तरीकों का उपभोग करते हैं।

सार्वजनिक विधियों पर अपनी इकाई परीक्षण चलाने से पहले डिबगिंग द्वारा निजी तरीकों का परीक्षण किया जाना चाहिए।

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

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


2
हालांकि यह सच है, यह कुछ बहुत ही जटिल परीक्षणों को जन्म दे सकता है - यह एक बेहतर तरीका है एक एकल विधि का परीक्षण करने के लिए (यूनिट परीक्षण) बल्कि उनके पूरे समूह के बजाय। एक भयानक सुझाव नहीं है, लेकिन मुझे लगता है कि यहां बेहतर जवाब हैं - यह एक अंतिम उपाय होना चाहिए।
बिल के

24

यदि स्प्रिंग का उपयोग किया जाता है, तो ReflectionTestUtils कुछ उपयोगी उपकरण प्रदान करता है जो न्यूनतम प्रयास के साथ यहां मदद करते हैं। उदाहरण के लिए, एक अवांछनीय सार्वजनिक सेटर को जोड़ने के लिए मजबूर किए बिना एक निजी सदस्य पर एक नकली सेट करने के लिए:

ReflectionTestUtils.setField(theClass, "theUnsettableField", theMockObject);

24

यदि आप मौजूदा कोड का परीक्षण करने की कोशिश कर रहे हैं जो आप अनिच्छुक हैं या बदलने में असमर्थ हैं, तो प्रतिबिंब एक अच्छा विकल्प है।

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

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


19

निजी तरीकों का परीक्षण आपकी कक्षा के इनकैप्सुलेशन को तोड़ता है क्योंकि हर बार जब आप आंतरिक कार्यान्वयन को बदलते हैं तो आप क्लाइंट कोड को तोड़ते हैं (इस मामले में, परीक्षण)।

इसलिए निजी तरीकों का परीक्षण न करें।


4
यूनिट टेस्ट और src कोड एक जोड़ी है। यदि आप src बदलते हैं, तो शायद आपको यूनिट टेस्ट बदलना होगा। यही जूनियर टेस्ट की समझ है। वे सभी कार्य पहले की तरह ही करेंगे। और अगर वे कोड बदलते हैं तो यह ठीक है।
एलेक्स्वियन जूल

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

16

JUnit.org FAQ पृष्ठ से उत्तर :

लेकिन अगर आपको ...

यदि आप JDK 1.3 या उच्चतर का उपयोग कर रहे हैं, तो आप PrivilegedAccessor की सहायता से अभिगम नियंत्रण तंत्र को वापस करने के लिए प्रतिबिंब का उपयोग कर सकते हैं । इसका उपयोग करने के तरीके के बारे में जानकारी के लिए, इस लेख को पढ़ें ।

यदि आप JDK 1.6 या उच्चतर का उपयोग कर रहे हैं और आप @ टेस्ट के साथ अपने परीक्षणों को एनोटेट करते हैं, तो आप अपने परीक्षण विधियों में प्रतिबिंब को इंजेक्ट करने के लिए Dp4j का उपयोग कर सकते हैं । इसका उपयोग करने के तरीके के विवरण के लिए, यह परीक्षण स्क्रिप्ट देखें ।

PS मैं Dp4j का मुख्य योगदानकर्ता हूं , मुझसे पूछें कि क्या आपको मदद चाहिए। :)


16

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


4
जॉकिट लाइब्रेरी के हिस्से के रूप में, आपके पास डीएन्कैप्सुलेशन क्लास तक पहुंच है जो निजी तरीकों का परीक्षण करना आसान बनाता है: Deencapsulation.invoke(instance, "privateMethod", param1, param2);
डोमिनिक डी।

मैं हर समय इस दृष्टिकोण का उपयोग करता हूं। बहुत उपयोगी
चिकित्सा

14

मैं निजी तरीकों का परीक्षण नहीं करता हूं। वहां पागलपन है। व्यक्तिगत रूप से, मेरा मानना ​​है कि आपको केवल अपने सार्वजनिक रूप से उजागर इंटरफेस (और जिसमें संरक्षित और आंतरिक तरीके शामिल हैं) का परीक्षण करना चाहिए।


14

यदि आप JUnit का उपयोग कर रहे हैं, तो junit-addons पर एक नज़र डालें । इसमें जावा सुरक्षा मॉडल को अनदेखा करने और निजी तरीकों और विशेषताओं तक पहुंचने की क्षमता है।


13

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

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

public class ClassToTest {

    private final String first = "first";
    private final List<String> second = new ArrayList<>();
    ...
}

मैंने इसका उपयोग किया है:

public class ClassToTest {

    private final String first;
    private final List<String> second;

    public ClassToTest() {
        this("first", new ArrayList<>());
    }

    public ClassToTest(final String first, final List<String> second) {
        this.first = first;
        this.second = second;
    }
    ...
}

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

अब निजी तरीकों के बारे में। मेरे व्यक्तिगत अनुभव में जब आपको परीक्षण के लिए एक निजी पद्धति को ठोकर मारना पड़ता है, तो उस पद्धति का उस कक्षा में कुछ भी नहीं होता है। एक सामान्य पैटर्न, उस स्थिति में, इसे एक इंटरफ़ेस के भीतर लपेटना होगा, जैसे कि Callableऔर फिर आप उस इंटरफ़ेस में भी कंस्ट्रक्टर में (उस कई कंस्ट्रक्टर ट्रिक के साथ) पास करते हैं:

public ClassToTest() {
    this(...);
}

public ClassToTest(final Callable<T> privateMethodLogic) {
    this.privateMethodLogic = privateMethodLogic;
}

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

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

सेटर इंजेक्शन भी है, लेकिन मैं इसका उपयोग करने की सिफारिश नहीं करूंगा। मैं एक कंस्ट्रक्टर के साथ रहना चाहता हूं और जब आवश्यक हो तो सब कुछ इनिशियलाइज़ कर सकता हूं, जिससे आवश्यक निर्भरता को इंजेक्ट करने की संभावना बढ़ जाएगी।


1
ClassToTest(Callable)इंजेक्शन से असहमत । यह ClassToTestऔर अधिक जटिल बनाता है। इसे सरल रखें। इसके अलावा, तब किसी और को ClassToTestकुछ बताने की आवश्यकता होती है जो कि ClassToTestबॉस होना चाहिए। तर्क को इंजेक्ट करने के लिए एक जगह है, लेकिन यह ऐसा नहीं है। आपने सिर्फ बनाए रखने के लिए वर्ग को कठिन बना दिया है, आसान नहीं।
Loduwijk

इसके अलावा, यह बेहतर है कि यदि आपके परीक्षण का तरीका उस बिंदु पर जटिलता को Xनहीं बढ़ाता Xहै जहां यह अधिक समस्याएं पैदा कर सकता है ... और इसलिए अतिरिक्त परीक्षण की आवश्यकता होती है ... जो कि यदि आपने इस तरह से लागू किया है जो अधिक समस्याएं पैदा कर सकता है .. ; (यह एक अनंत लूप नहीं है; प्रत्येक पुनरावृति इसके पहले एक से छोटी होने की संभावना है, लेकिन फिर भी कष्टप्रद है)
Loduwijk

2
क्या आप बता सकते हैं कि क्लास ClassToTestको बनाए रखना कठिन क्यों होगा ? वास्तव में यह आपके आवेदन को बनाए रखना आसान बनाता है, आप क्या सुझाव देते हैं कि आपको हर दूसरे मूल्य के लिए नए वर्ग बनाने की आवश्यकता होगी जो आपको first'दूसरे' चर में चाहिए?
18 नवंबर को GROX13

1
परीक्षण की विधि जटिलता नहीं बढ़ाती है। यह सिर्फ आपकी कक्षा है जो खराब लिखी गई है, इतनी खराब है कि इसका परीक्षण नहीं किया जा सकता है।
18 नवंबर को जीओएक्स 13

बनाए रखने के लिए कठोर क्योंकि वर्ग अधिक जटिल है। class A{ A(){} f(){} }से सरल है class A { Logic f; A(logic_f) } class B { g() { new A( logic_f) } }। यदि यह सच नहीं था, और अगर यह सच था कि एक वर्ग के तर्क की आपूर्ति करना क्योंकि निर्माण तर्क को बनाए रखना आसान था, तो हम सभी तर्क को निर्माता तर्क के रूप में पारित करेंगे। मैं सिर्फ यह नहीं देखता कि आप कैसे दावा कर सकते हैं कि class B{ g() { new A( you_dont_know_your_own_logic_but_I_do ) } }ए को बनाए रखना आसान है। ऐसे मामले हैं जहां इस तरह इंजेक्शन लगाने से समझ में आता है, लेकिन मैं आपके उदाहरण को "बनाए रखने में आसान" के रूप में नहीं देखता हूं
Loduwijk

12

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

और फिर एक संरक्षित पद्धति को केवल उसी पैकेज के भीतर एक्सेस किया जा सकता है जहां कक्षा परिभाषित है। तो, लक्ष्य वर्ग की एक संरक्षित पद्धति का परीक्षण करने का मतलब है कि हमें अपने परीक्षण वर्ग को उसी लक्ष्य वर्ग के रूप में परिभाषित करना होगा।

यदि उपरोक्त सभी आपकी आवश्यकता के अनुरूप नहीं है, तो निजी विधि का उपयोग करने के लिए प्रतिबिंब तरीके का उपयोग करें।


आप "दोस्ताना" के साथ "संरक्षित" मिश्रण कर रहे हैं। एक संरक्षित पद्धति को केवल उस वर्ग द्वारा एक्सेस किया जा सकता है, जिसकी वस्तुएं लक्षित वर्ग (यानी उपवर्ग) के लिए असाइन की जा सकती हैं।
सायो ओलदेजी

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

मैंने लगभग पूरी तरह से सोच लिया, "यह जवाब सिर्फ सादा गलत है।" जब तक मुझे बहुत अंतिम सजा नहीं मिल जाती, जो बाकी के उत्तर का खंडन करता है। अंतिम वाक्य पहले होना चाहिए था।
लोदविजक

11

जैसा कि ऊपर कई ने सुझाव दिया है, एक अच्छा तरीका है कि आप अपने सार्वजनिक इंटरफेस के माध्यम से उनका परीक्षण करें।

यदि आप ऐसा करते हैं, तो यह देखना एक अच्छा विचार है कि कोड कवरेज टूल (जैसे एम्मा) का उपयोग करें कि क्या आपके निजी तरीकों को वास्तव में आपके परीक्षणों से निष्पादित किया जा रहा है।


आपको परोक्ष रूप से परीक्षण नहीं करना चाहिए! न केवल कवरेज के माध्यम से छू; परीक्षण करें कि अपेक्षित परिणाम दिया गया है!
एलेक्सजेन

11

यहाँ निजी क्षेत्रों का परीक्षण करने के लिए मेरा सामान्य कार्य है:

protected <F> F getPrivateField(String fieldName, Object obj)
    throws NoSuchFieldException, IllegalAccessException {
    Field field =
        obj.getClass().getDeclaredField(fieldName);

    field.setAccessible(true);
    return (F)field.get(obj);
}

10

एक उदाहरण के लिए नीचे देखें;

निम्नलिखित आयात विवरण जोड़ा जाना चाहिए:

import org.powermock.reflect.Whitebox;

अब आप सीधे उस ऑब्जेक्ट को पास कर सकते हैं जिसमें निजी विधि, विधि का नाम कहा जाता है, और नीचे के रूप में अतिरिक्त पैरामीटर।

Whitebox.invokeMethod(obj, "privateMethod", "param1");

10

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

यदि आपको निजी विधियों या फ़ील्ड्स या कंस्ट्रक्टर्स के साथ कुछ कोड मिला है, तो आप बाउंडबॉक्स का उपयोग कर सकते हैं । यह वही करता है जो आप ढूंढ रहे हैं। नीचे एक परीक्षण का एक उदाहरण दिया गया है जो इसे परीक्षण करने के लिए एंड्रॉइड गतिविधि के दो निजी क्षेत्रों तक पहुंचता है:

@UiThreadTest
public void testCompute() {

    // Given
    boundBoxOfMainActivity = new BoundBoxOfMainActivity(getActivity());

    // When
    boundBoxOfMainActivity.boundBox_getButtonMain().performClick();

    // Then
    assertEquals("42", boundBoxOfMainActivity.boundBox_getTextViewMain().getText());
}

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

यह कुछ विरासत कोड के परीक्षण के लिए आदर्श है। इसका प्रयोग सावधानी से करें। ;)

https://github.com/stephanenicolas/boundbox


1
बस यह कोशिश की, बाउंडबॉक्स एक सरल और सुरुचिपूर्ण और समाधान है!
फोर्थ

9

सबसे पहले, मैं इस प्रश्न को बाहर निकाल दूंगा: आपके निजी सदस्यों को पृथक परीक्षण की आवश्यकता क्यों है? क्या वे उस जटिल हैं, जो इस तरह के जटिल व्यवहार प्रदान करते हैं जैसे कि सार्वजनिक सतह से अलग परीक्षण की आवश्यकता होती है? यह इकाई परीक्षण है, न कि 'लाइन-ऑफ-कोड' परीक्षण। छोटे सामान पसीना मत करो।

यदि वे इतने बड़े, बड़े पर्याप्त हैं कि ये निजी सदस्य प्रत्येक 'इकाई' की जटिलता में बड़े हैं - तो ऐसे निजी सदस्यों को इस वर्ग से बाहर करने पर विचार करें।

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


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

यहां तक ​​कि कभी-कभी इकाई परीक्षण के बिना सबसे छोटा कोड भी सही नहीं है। बस 2 geograhpical कोणों के बीच अंतर को शांत करने का प्रयास करें। कोड की 4 लाइनें, और अधिकांश इसे पहले प्रयास में सही नहीं करेंगे। इस तरह के तरीकों के लिए यूनिट टेस्ट की आवश्यकता होती है, क्योंकि फॉर्म एक भरोसेमंद कोड का आधार होता है। (Ans ऐसा उपयोगी कोड सार्वजनिक भी हो सकता है; कम उपयोगी संरक्षित)
एलेक्सियन

8

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

कॉलिंग के तरीके, जैसे private void method(String s)- जावा प्रतिबिंब द्वारा

Method method = targetClass.getDeclaredMethod("method", String.class);
method.setAccessible(true);
return method.invoke(targetObject, "mystring");

कॉलिंग के तरीके, जैसे private void method(String s)- पिकलॉक द्वारा

interface Accessible {
  void method(String s);
}

...
Accessible a = ObjectAccess.unlock(targetObject).features(Accessible.class);
a.method("mystring");

फ़ील्ड सेट करना, जैसे private BigInteger amount;- जावा प्रतिबिंब द्वारा

Field field = targetClass.getDeclaredField("amount");
field.setAccessible(true);
field.set(object, BigInteger.valueOf(42));

फ़ील्ड सेट करना, जैसे private BigInteger amount;- पिकलॉक द्वारा

interface Accessible {
  void setAmount(BigInteger amount);
}

...
Accessible a = ObjectAccess.unlock(targetObject).features(Accessible.class);
a.setAmount(BigInteger.valueOf(42));

7

इसके लिए पावरमॉकिटो बनाया गया है। मावेन निर्भरता का उपयोग करें

<dependency>
    <groupId>org.powermock</groupId>
    <artifactId>powermock-mockito-release-full</artifactId>
    <version>1.6.4</version>
</dependency>

तब आप कर सकते हैं

import org.powermock.reflect.Whitebox;
...
MyClass sut = new MyClass();
SomeType rval = Whitebox.invokeMethod(sut, "myPrivateMethod", params, moreParams);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.