java - यूनिट परीक्षण में प्रतिबिंब का उपयोग करने के लिए यह बुरा अभ्यास है?




unit-testing reflection (5)

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

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

प्रतिबिंब का उपयोग करने के लिए यह वास्तव में बुरा अभ्यास है? मैं वास्तव में विश्वास नहीं कर सकता कि-

संपादित करें: मुझे यह उल्लेख करना चाहिए था कि मुझे यह आवश्यक था कि सभी परीक्षण परीक्षण नामक एक अलग पैकेज में हों (इसलिए संरक्षित दृश्यता का उपयोग करना जैसे एक संभावित समाधान भी नहीं था)


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

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

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

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


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

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


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

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

उदाहरण के लिए वसंत ReflectionTestUtils । लेकिन इसका उद्देश्य निर्भरताओं के झुंड सेट है, जहां वसंत उन्हें इंजेक्ट करना था।

विषय "क्या करें और नहीं" से गहरा है, और इस बात का सम्मान करता है कि क्या परीक्षण किया जाना चाहिए - क्या वस्तुओं की आंतरिक स्थिति का परीक्षण किया जाना चाहिए या नहीं; चाहे हमें परीक्षा के तहत कक्षा के डिजाइन पर सवाल उठाना चाहिए; आदि।


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

कम से कम, यूनिट परीक्षण प्रक्रिया में यह मेरी सोच है।


मैं बोझो का विचार दूसरा:

परीक्षण के लिए केवल उत्पादन एपीआई की दृश्यता को संशोधित करना वास्तव में बुरा है।

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

केवल परीक्षण के लिए सुलभ पहुंच के जाल में गिरने के बाद और फिर अनजाने में अन्य उत्पादन कोड से निजी-निजी विधि तक पहुंचने के लिए मैंने डीपी 4j.jar के बारे में सोचा: यह प्रतिबिंब एपीआई कोड ( Lombok-style ) इंजेक्ट करता है ताकि आप नहीं बदल सकें उत्पादन कोड और प्रतिबिंब एपीआई खुद को मत लिखो; डीपी 4 जे संकलन समय पर समकक्ष प्रतिबिंब एपीआई के साथ इकाई परीक्षण में आपकी सीधी पहुंच को प्रतिस्थापित करता है। यहां जुनीट के साथ डीपी 4 जे का एक उदाहरण दिया गया है






reflection