इकाई परीक्षण करते समय सी # "आंतरिक" एक्सेस संशोधक


469

मैं यूनिट परीक्षण में नया हूँ और मुझे यह पता लगाने की कोशिश की जा रही है कि क्या मुझे 'आंतरिक' एक्सेस संशोधक का अधिक उपयोग शुरू करना चाहिए। मुझे पता है कि अगर हम 'इंटरनल' का इस्तेमाल करते हैं और असेंबली वैरिएबल 'इंटरनैशनलविजेंटो' को सेट करते हैं, तो हम उन फंक्शन को टेस्ट कर सकते हैं जिन्हें हम टेस्टिंग प्रोजेक्ट से पब्लिक घोषित नहीं करना चाहते। इससे मुझे लगता है कि मुझे हमेशा 'आंतरिक' का उपयोग करना चाहिए क्योंकि कम से कम प्रत्येक परियोजना (चाहिए?) की खुद की परीक्षण परियोजना है। क्या तुम लोग मुझे एक कारण बता सकते हो कि मुझे ऐसा क्यों नहीं करना चाहिए? मुझे 'निजी' का उपयोग कब करना चाहिए?


1
वर्थ उल्लेख - आप अक्सर अपने System.Diagnostics.Debug.Assert()स्वयं के तरीकों का उपयोग करके अपने आंतरिक तरीकों के परीक्षण के लिए यूनिट की आवश्यकता से बच सकते हैं।
माइक मैरीनोव्स्की

जवाबों:


1195

आंतरिक कक्षाओं का परीक्षण करने की आवश्यकता है और एक विशेषता है:

using System.Runtime.CompilerServices;

[assembly:InternalsVisibleTo("MyTests")]

प्रोजेक्ट जानकारी फ़ाइल में इसे जोड़ें, उदा Properties\AssemblyInfo.cs


70
इसे परीक्षण के तहत परियोजना में जोड़ें (उदाहरण के लिए Properties \ AssemblyInfo.cs में)। "MyTests" टेस्ट असेंबली होगी।
एरिकशोफर

86
यह वास्तव में स्वीकृत उत्तर होना चाहिए। मुझे आप लोगों के बारे में पता नहीं है, लेकिन जब परीक्षण उस कोड से "बहुत दूर" हो जाते हैं, जिसका मैं परीक्षण करता हूं तो मुझे घबराहट होती है। मैं सभी के रूप में चिह्नित कुछ भी परीक्षण करने से बचने के लिए हूँ private, लेकिन बहुत सी privateचीजें एक internalवर्ग को बहुत अच्छी तरह से इंगित कर सकती हैं जो निकालने के लिए संघर्ष कर रहा है। TDD या नो TDD, मैं अधिक परीक्षणों का परीक्षण करना पसंद करता हूँ जो बहुत सारे कोड का परीक्षण करते हैं, कुछ परीक्षण करने की तुलना में जो कोड की समान मात्रा का उपयोग करते हैं। और internalसामान का परीक्षण करने से बचना एक अच्छा अनुपात प्राप्त करने में मदद नहीं करता है।
एस एम

7
आंतरिक और निजी और आंतरिक घटकों का परीक्षण करने की आवश्यकता के बीच शब्दार्थ अंतर के बारे में @DerickBailey और Dan Tao के बीच बहुत अच्छी चर्चा चल रही है । अच्छी तरह से पढ़ने लायक।
क्रिस मैकगिनेंस

31
में लपेटकर और #if DEBUG, #endifब्लॉक केवल डिबग बिल्ड में इस विकल्प को सक्षम करेगा।
असली एडवर्ड कलन

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

127

आप निजी तरीकों का परीक्षण करना चाहते हैं, पर एक नजर है PrivateObjectऔर PrivateTypeमें Microsoft.VisualStudio.TestTools.UnitTestingनाम स्थान। वे आवश्यक प्रतिबिंब कोड के आसपास रैपर का उपयोग करना आसान बनाते हैं।

डॉक्स: PrivateType , PrivateObject

VS2017 और 2019 के लिए, आप MSTest.TestFramework nuget को डाउनलोड करके इन्हें पा सकते हैं


15
जब नीचे मतदान कृपया एक टिप्पणी छोड़ दें। धन्यवाद।
ब्रायन रासमुसेन

35
यह जवाब देने के लिए मूर्खतापूर्ण मतदान है। यह एक नए समाधान की ओर इशारा करता है और वास्तव में अच्छा है जिसका पहले उल्लेख नहीं किया गया है।
इग्नासियो सोलर गार्सिया

जाहिर है, वहाँ कुछ समस्या w / अनुप्रयोग लक्ष्यीकरण के लिए TestFramework का उपयोग कर रहा है .net2.0 या नए: github.com/Microsoft/testfx/issues/366
जॉनी वू

41

एरिक के जवाब में जोड़कर, आप इसे csprojफ़ाइल में भी कॉन्फ़िगर कर सकते हैं :

<ItemGroup>
    <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
      <_Parameter1>MyTests</_Parameter1>
    </AssemblyAttribute>
</ItemGroup>

या यदि आपके पास परीक्षण के लिए प्रति परियोजना एक परीक्षण परियोजना है, तो आप अपनी Directory.Build.propsफ़ाइल में ऐसा कुछ कर सकते हैं :

<ItemGroup>
    <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleTo">
      <_Parameter1>$(MSBuildProjectName).Test</_Parameter1>
    </AssemblyAttribute>
</ItemGroup>

देखें: https://stackoverflow.com/a/49978185/1678053
उदाहरण: https://github.com/gldraphael/evlog/blob/master/Directory.Build.props#L5-L12


2
यह शीर्ष उत्तर imo होना चाहिए। अन्य सभी उत्तर बहुत पुराने हैं क्योंकि .नेट असेंबली की जानकारी से दूर जा रहा है और कार्यक्षमता को csproj परिभाषाओं में स्थानांतरित कर रहा है।
mBrice1024

12

डिफ़ॉल्ट रूप से निजी का उपयोग करते रहें। यदि किसी सदस्य को उस प्रकार से आगे नहीं जाना चाहिए, तो उसे उस प्रकार से परे उजागर नहीं किया जाना चाहिए, यहां तक ​​कि उसी परियोजना के भीतर भी। यह चीजों को सुरक्षित और ख़ुश रखता है - जब आप ऑब्जेक्ट का उपयोग कर रहे हैं, तो यह स्पष्ट है कि आप किन तरीकों का उपयोग करने में सक्षम हैं।

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

एक बात पर विचार करने के लिए एक "ForTest" प्रत्यय हो सकता है:

internal void DoThisForTest(string name)
{
    DoThis(name);
}

private void DoThis(string name)
{
    // Real implementation
}

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


2
यदि विधि आंतरिक है, तो यह परीक्षण विधानसभा से इसके उपयोग को रोकता नहीं है?
राल्फ शिलिंग्टन

7
मैं कभी-कभी ForTestदृष्टिकोण का उपयोग करता हूं, लेकिन मुझे हमेशा यह मृत बदसूरत लगता है (कोड जोड़ना जो उत्पादन व्यवसाय तर्क के संदर्भ में कोई वास्तविक मूल्य प्रदान नहीं करता है)। आमतौर पर मुझे लगता है कि मुझे दृष्टिकोण का उपयोग करना पड़ा क्योंकि डिजाइन बहुत दुर्भाग्यपूर्ण है (यानी परीक्षण के बीच सिंगलटन उदाहरणों को रीसेट करने के लिए)
क्रिसव्यू

1
इसको कम करने के लिए प्रलोभन दिया गया - इस हैक के बीच क्या अंतर है और बस वर्ग को निजी के बजाय आंतरिक बना रहा है? ठीक है, कम से कम संकलन शर्तों के साथ। तब यह वास्तव में गड़बड़ हो जाता है।
सीएडी

6
@ कैडब्लोके: क्या आपका मतलब निजी के बजाय विधि को आंतरिक बनाना है ? अंतर यह है कि यह स्पष्ट है कि आप वास्तव में निजी होना चाहते हैं । आपके उत्पादन कोडबेस के भीतर कोई भी कोड, जिसके साथ किसी विधि को कॉल ForTestकरना स्पष्ट रूप से गलत है, जबकि यदि आप केवल विधि को आंतरिक बनाते हैं तो ऐसा लगता है कि यह उपयोग करने के लिए ठीक है।
जॉन स्कीट

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

11

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

http://www.codeproject.com/KB/cs/testnonpublicmembers.aspx

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


3

मैं उपयोग कर रहा हूं Dotnet 3.1.101और .csprojमेरे लिए काम करने वाले अतिरिक्त थे:

<PropertyGroup>
  <!-- Explicitly generate Assembly Info -->
  <GenerateAssemblyInfo>true</GenerateAssemblyInfo>
</PropertyGroup>

<ItemGroup>
  <AssemblyAttribute Include="System.Runtime.CompilerServices.InternalsVisibleToAttribute">
  <_Parameter1>MyProject.Tests</_Parameter1>
  </AssemblyAttribute>
</ItemGroup>

आशा है कि यह किसी को वहाँ मदद करता है!


1
स्पष्ट रूप से विधानसभा जानकारी उत्पन्न करने के अलावा आखिरकार यह मेरे लिए भी काम कर गया। इसे पोस्ट करने के लिए आपका धन्यवाद!
thevioletsaber
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.