कोड को आंतरिक बनाना लेकिन अन्य परियोजनाओं से इकाई परीक्षण के लिए उपलब्ध है


129

हम अपने सभी प्रोजेक्ट परीक्षण अपने स्वयं के प्रोजेक्ट में लगाते हैं। हम पाते हैं कि हमें केवल यूनिट परीक्षणों के लिए आंतरिक के बजाय कुछ वर्गों को सार्वजनिक करना होगा। वहाँ ऐसा करने से बचने के लिए वैसे भी है। सील के बजाय कक्षाओं को सार्वजनिक करके मेमोरी निहितार्थ क्या हैं?


जवाबों:


205

यदि आप .NET का उपयोग कर रहे हैं, तो InternalsVanishTo असेंबली विशेषता आपको "मित्र" असेंबली बनाने की अनुमति देती है। ये विशिष्ट रूप से नामित विधानसभाएं हैं जिन्हें आंतरिक कक्षाओं और अन्य विधानसभा के सदस्यों तक पहुंचने की अनुमति है।

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

उदाहरण:

[assembly: InternalsVisibleTo("NameAssemblyYouWantToPermitAccess")]
namespace NameOfYourNameSpace
{

23
मेरा सुझाव है कि विशेषता के चारों ओर एक # डेबग लगाएं, और फिर डीबग में इकाई परीक्षण करें। इस तरह आप सुनिश्चित करेंगे कि विशेषता रिलीज़ कोड पर सेट नहीं है।
कुक

यह सिर्फ एक विचार है, मुझे नहीं पता .... कैसे के बारे में: #if DEBUG सार्वजनिक वर्ग IniReader #else आंतरिक वर्ग IniReader #endif शायद अनुशंसित नहीं है? क्यों?
jmelhus

4
खैर, डीबग करने के लिए परीक्षणों को सीमित क्यों करता है?
मार्को Mp

2
इसके अलावा, सिर्फ एक निपिक, "मित्र" असेंबली को दृढ़ता से नाम देने की कोई आवश्यकता नहीं है (एक अच्छा अभ्यास हो सकता है - भले ही मेरा व्यक्तिगत स्वाद अन्यथा न कहे)।
मार्को Mp

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

6

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

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

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

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


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

69
जरूरी नहीं कि मैं इससे सहमत हूं क्योंकि ये वर्ग डीएलएल के अंदर अन्य वर्गों के लिए "सार्वजनिक" हैं और वर्ग की कार्यक्षमता का अनिश्चित काल तक परीक्षण किया जाना चाहिए
leora

27
मैं भी सहमत नहीं हूं। इकाइयां इकाइयां हैं और उन्हें अलगाव में परीक्षण किया जाना चाहिए।
प्रहरी

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

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

4

प्रलेखन उद्देश्यों के लिए

वैकल्पिक रूप से आप Type.GetTypeविधि का उपयोग करके आंतरिक वर्ग को त्वरित कर सकते हैं

उदाहरण

//IServiceWrapper is public class which is 
//the same assembly with the internal class 
var asm = typeof(IServiceWrapper).Assembly;
//Namespace.ServiceWrapper is internal
var type = asm.GetType("Namespace.ServiceWrapper");
return (IServiceWrapper<T>)Activator
    .CreateInstance(type, new object[1] { /*constructor parameter*/ });

सामान्य प्रकार के लिए bellow के रूप में अलग प्रक्रिया है:

var asm = typeof(IServiceWrapper).Assembly;
//note the name Namespace.ServiceWrapper`1
//this is for calling Namespace.ServiceWrapper<>
var type = asm.GetType("Namespace.ServiceWrapper`1");
var genType = type.MakeGenericType(new Type[1] { typeof(T) });
return (IServiceWrapper<T>)Activator
     .CreateInstance(genType, new object[1] { /*constructor parameter*/});

-5

कक्षाएं सार्वजनिक और सील दोनों हो सकती हैं।

लेकिन, ऐसा मत करो।

आप आंतरिक कक्षाओं को प्रतिबिंबित करने के लिए एक उपकरण बना सकते हैं, और एक नए वर्ग का उत्सर्जन कर सकते हैं जो प्रतिबिंब के माध्यम से सब कुछ एक्सेस करता है। MSTest ऐसा करता है।

संपादित करें: मेरा मतलब है, यदि आप अपनी मूल असेंबली में-परीक्षण सामग्री शामिल करना नहीं चाहते हैं; यह भी काम करता है अगर सदस्य निजी हैं।


1
रुको क्या? आप कह रहे हैं कि एक मत करो public sealed class? उस मणि के लिए आपका तर्क क्या है?
क्रश

@ क्रश ट्रैम्पैनी 2009 के बाद से लॉग इन नहीं हुआ है।
प्रो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.