سؤال

أقوم بإنشاء مكتبة صفية تحتوي على بعض الأساليب العامة والخاصة.أريد أن أكون قادرًا على اختبار الوحدة للطرق الخاصة (في الغالب أثناء التطوير، ولكنها قد تكون مفيدة أيضًا لإعادة البناء في المستقبل).

ما هي الطريقة الصحيحة للقيام بذلك؟

هل كانت مفيدة؟

المحلول

إذا كنت تستخدم الصافية، يجب عليك استخدام في InternalsVisibleToAttribute .

نصائح أخرى

إذا كنت تريد اختبار الوحدة لطريقة خاصة، فقد يكون هناك خطأ ما.تهدف اختبارات الوحدة (بشكل عام) إلى اختبار واجهة الفصل، أي أساليبها العامة (والمحمية).يمكنك بالطبع "اختراق" حل لهذا (حتى لو كان ذلك فقط عن طريق جعل الطرق عامة)، ولكن قد ترغب أيضًا في التفكير في:

  1. إذا كانت الطريقة التي ترغب في اختبارها تستحق الاختبار حقًا، فقد يكون من المفيد نقلها إلى فئتها الخاصة.
  2. أضف المزيد من الاختبارات إلى الطرق العامة التي تستدعي الطريقة الخاصة، واختبر وظائف الطريقة الخاصة.(كما أشار المعلقون، يجب عليك القيام بذلك فقط إذا كانت وظيفة هذه الأساليب الخاصة جزءًا من الواجهة العامة.إذا كانوا يقومون بالفعل بوظائف مخفية عن المستخدم (أياختبار الوحدة)، ربما يكون هذا سيئًا).

قد لا يكون من المفيد اختبار الأساليب الخاصة.ومع ذلك، أحيانًا أحب أيضًا استدعاء الطرق الخاصة من طرق الاختبار.في معظم الأحيان من أجل منع تكرار التعليمات البرمجية لإنشاء بيانات الاختبار ...

توفر Microsoft آليتين لهذا:

الملحقات

  • انتقل إلى الكود المصدري لتعريف الفصل
  • انقر بزر الماوس الأيمن على اسم الفصل
  • اختر "إنشاء ملحق خاص"
  • اختر المشروع الذي يجب إنشاء الملحق => سوف ينتهي بك الأمر بفصول جديدة باسم Foo_Accessor.سيتم إنشاء هذا الفصل ديناميكيًا أثناء التجميع وسيوفر لجميع الأعضاء المتاحين للعامة.

ومع ذلك، تكون الآلية في بعض الأحيان مستعصية بعض الشيء عندما يتعلق الأمر بتغييرات واجهة الفئة الأصلية.لذلك، في أغلب الأحيان أتجنب استخدام هذا.

فئة كائن خاصوالطريقة الأخرى هي استخدام Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject

// Wrap an already existing instance
PrivateObject accessor = new PrivateObject( objectInstanceToBeWrapped );

// Retrieve a private field
MyReturnType accessiblePrivateField = (MyReturnType) accessor.GetField( "privateFieldName" );

// Call a private method
accessor.Invoke( "PrivateMethodName", new Object[] {/* ... */} );

وأنا لا أتفق مع فلسفة "يجب أن تكون مهتمة في اختبار الواجهة الخارجية فقط". انها قليلا مثل قوله أن ورشة لاصلاح السيارات ينبغي أن يكون اختبارات لمعرفة ما إذا بدوره العجلات فقط. نعم، في النهاية أنا مهتم في السلوك الخارجي لكني أحب بلدي، والاختبارات الداخلية خاصة أن يكون قليلا أكثر تحديدا وإلى هذه النقطة. نعم، إذا كنت ريفاكتور، وأنا قد تضطر إلى تغيير بعض الاختبارات، ولكن إلا إذا كان ريفاكتور ضخمة، سآخذ فقط لتغيير عدد قليل، وحقيقة أن (لم يتغير) الاختبارات الداخلية الأخرى لا تزال تعمل هو مؤشر كبير أن وقد تم إعادة بيع ديون ناجحة.

ويمكنك محاولة لتغطية جميع الحالات الداخلية فقط باستخدام واجهة العامة ونظريا من الممكن لاختبار كل أسلوب داخلي (أو على الأقل كل واحد ما يهم) تماما باستخدام واجهة العامة ولكن قد تضطر في نهاية المطاف واقفا على الخاص رئيس لتحقيق ذلك، والعلاقة بين حالات الاختبار تدار من خلال واجهة العامة والجزء الداخلي من الحل أنها مصممة لاختبار قد يكون من الصعب أو من المستحيل تمييز. وبعد أن أشار والاختبارات الفردية التي تضمن تعمل الآلات الداخلية بشكل صحيح تستحق التغييرات الطفيفة التي تأتي اختبار حول مع إعادة بيع ديون - على الأقل هذا ما كان تجربتي. إذا كان لديك لإجراء تغييرات ضخمة لاختبارات للحصول على كل إعادة بيع ديون، ثم ربما هذا لا معنى له، ولكن في هذه الحالة، ربما يجب عليك أن تعيد التفكير في التصميم الخاص بك تماما. وينبغي أن يكون التصميم الجيد مرنة بما فيه الكفاية للسماح لمعظم التغييرات دون إعادة التصميم واسعة النطاق.

في الحالات النادرة لقد أراد أن يختبر وظائف خاصة، وأنا عدلت عادة لهم في الحماية بدلا من ذلك، وكنت قد كتبت فرعية مع وظيفة المجمع العامة.

ومن الدرجة الاولى:

...

protected void APrivateFunction()
{
    ...
}

...

والفئة الفرعية للاختبار:

...

[Test]
public void TestAPrivateFunction()
{
    APrivateFunction();
    //or whatever testing code you want here
}

...

وأعتقد أنه يجب طرح السؤال الأكثر جوهرية هو أن لماذا تحاول أن اختبار الأسلوب الخاص في المقام الأول. هذا هو رائحة التعليمات البرمجية التي كنت تحاول اختبار الأسلوب الخاص من خلال تلك الفئة "الواجهة العمومية في حين أن الأسلوب هو خاص لسبب كما انها تفصيل تطبيق. واحد يجب فقط أن تهتم سلوك الواجهة العمومية وليس على كيف انها نفذت تحت الأغطية.

إذا أريد لاختبار سلوك أسلوب خاص، وذلك باستخدام refactorings المشتركة، ويمكن استخراج رمزها في فئة أخرى (ربما مع وضوح مستوى حزمة لذا تأكد انها ليست جزءا من API العام). يمكنني ثم اختبار سلوكها في العزلة.

والمنتج من إعادة بيع ديون يعني أن الأسلوب الخاص هو الآن فئة منفصلة الذي أصبح متعاون للطبقة الأصلية. وأصبحت سلوكها مفهومة جيدا من خلال وحدة الاختبارات الخاصة بها.

وبعد ذلك يمكنني أن يسخر سلوكها عندما أحاول اختبار الطبقة الأصلية بحيث يمكنني ثم التركيز على اختبار سلوك تلك الفئة "الواجهة العمومية بدلا من الاضطرار لاختبار انفجار اندماجي من الواجهة العمومية وسلوك جميع الطرق الخاصة.

وأرى أن هذا مماثلة لقيادة السيارة. عندما أقود السيارة وأنا لا تدفع مع غطاء محرك السيارة تصل حتى أستطيع أن أرى أن المحرك يعمل. أنا أعتمد على واجهة توفر السيارة، وهي عداد دوران المحرك وعداد السرعة لمعرفة محرك يعمل. أنا أعتمد على حقيقة أن السيارة تتحرك فعلا عندما كنت اضغط على دواسة البنزين. إذا كنت ترغب في اختبار محرك يمكنني القيام به الشيكات على ذلك في العزلة. : D

وبطبيعة الحال اختبار أساليب خاصة مباشرة قد يكون الملاذ الأخير إذا كان لديك تطبيق إرث ولكن أود أن تفضل وريفاكتوريد هذا الرمز إرث لتمكين اختبار أفضل. مايكل الريش قد كتب كتابا كبيرا على هذا الموضوع جدا. http://www.amazon.co.uk/Working-Effectively-Legacy- روبرت مارتن / موانئ دبي / 0131177052

وأنواع خاصة، الداخلية وأعضاء من القطاع الخاص وذلك بسبب بعض السبب، وكثيرا ما كنت لا تريد الفوضى معهم مباشرة. وإذا قمت بذلك، وهناك احتمالات أن عليك كسر في وقت لاحق، وذلك لأن ليس هناك ما يضمن أن الرجال الذين خلقوا تلك المجالس سيبقي تطبيقات خاصة / الداخلية على هذا النحو.

ولكن، في بعض الأحيان، عندما تفعل بعض الخارقة / استكشاف المجالس حزب المترجمة أو الثالثة، ولدي انتهت نفسي الرغبة في تهيئة فئة خاصة أو فئة مع منشئ خاص أو الداخلي. أو، في بعض الأحيان، عند التعامل مع المكتبات تراث ما قبل تجميعها أنني لا يمكن تغيير - أنا في نهاية المطاف كتابة بعض الاختبارات على طريقة الخاص

وهكذا ولد AccessPrivateWrapper - HTTP: //amazedsaint.blogspot كوم / 2010/05 / accessprivatewrapper-ج-40-dynamic.html - انها هي فئة المجمع السريعة التي سوف تجعل هذه المهمة سهلة باستخدام C # 4.0 ميزات ديناميكية والتأمل

ويمكنك إنشاء أنواع الداخلية / خاصة مثل

    //Note that the wrapper is dynamic
    dynamic wrapper = AccessPrivateWrapper.FromType
        (typeof(SomeKnownClass).Assembly,"ClassWithPrivateConstructor");

    //Access the private members
    wrapper.PrivateMethodInPrivateClass();

حسنًا، يمكنك وحدة اختبار الطريقة الخاصة بطريقتين

  1. يمكنك إنشاء مثيل ل PrivateObject فئة بناء الجملة هو كما يلي

    PrivateObject obj= new PrivateObject(PrivateClass);
    //now with this obj you can call the private method of PrivateCalss.
    obj.PrivateMethod("Parameters");
    
  2. يمكنك استخدام الانعكاس.

    PrivateClass obj = new PrivateClass(); // Class containing private obj
    Type t = typeof(PrivateClass); 
    var x = t.InvokeMember("PrivateFunc", 
        BindingFlags.InvokeMethod | BindingFlags.NonPublic | BindingFlags.Public |  
            BindingFlags.Instance, null, obj, new object[] { 5 });
    

ولقد استعملت أيضا طريقة InternalsVisibleToAttribute. ومن الجدير بالذكر أيضا أنه إذا كنت تشعر بعدم الارتياح اتخاذ أساليب خاصة من قبل بك الداخلية من أجل تحقيق ذلك، ثم ربما لا ينبغي أن يكون موضوع وحدة الاختبارات المباشرة على أي حال.

وبعد كل شيء، كنت اختبار <م> السلوك من الفئة الخاصة بك، وليس كل شيء <م> محددة للتنفيذ - يمكنك تغيير هذا الأخير من دون تغيير السابق والاختبارات الخاصة بك لا يزال ينبغي تمر.

هناك نوعان من الطرق الخاصة.الطرق الخاصة الثابتة والأساليب الخاصة غير الثابتة (طرق المثيل).تشرح المقالتان التاليتان كيفية وحدة اختبار الأساليب الخاصة مع الأمثلة.

  1. وحدة اختبار الطرق الخاصة الثابتة
  2. وحدة اختبار الطرق الخاصة غير الثابتة

وMS اختبار لديه ميزة جميلة بنيت في أن يجعل أعضاء الخاص والأساليب المتاحة في المشروع عن طريق إنشاء ملف يسمى VSCodeGenAccessors

[System.Diagnostics.DebuggerStepThrough()]
    [System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TestTools.UnitTestGeneration", "1.0.0.0")]
    internal class BaseAccessor
    {

        protected Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject m_privateObject;

        protected BaseAccessor(object target, Microsoft.VisualStudio.TestTools.UnitTesting.PrivateType type)
        {
            m_privateObject = new Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject(target, type);
        }

        protected BaseAccessor(Microsoft.VisualStudio.TestTools.UnitTesting.PrivateType type)
            :
                this(null, type)
        {
        }

        internal virtual object Target
        {
            get
            {
                return m_privateObject.Target;
            }
        }

        public override string ToString()
        {
            return this.Target.ToString();
        }

        public override bool Equals(object obj)
        {
            if (typeof(BaseAccessor).IsInstanceOfType(obj))
            {
                obj = ((BaseAccessor)(obj)).Target;
            }
            return this.Target.Equals(obj);
        }

        public override int GetHashCode()
        {
            return this.Target.GetHashCode();
        }
    }

ومع الفئات التي تنبع من BaseAccessor

ومثل

[System.Diagnostics.DebuggerStepThrough()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TestTools.UnitTestGeneration", "1.0.0.0")]
internal class SomeClassAccessor : BaseAccessor
{

    protected static Microsoft.VisualStudio.TestTools.UnitTesting.PrivateType m_privateType = new Microsoft.VisualStudio.TestTools.UnitTesting.PrivateType(typeof(global::Namespace.SomeClass));

    internal SomeClassAccessor(global::Namespace.Someclass target)
        : base(target, m_privateType)
    {
    }

    internal static string STATIC_STRING
    {
        get
        {
            string ret = ((string)(m_privateType.GetStaticField("STATIC_STRING")));
            return ret;
        }
        set
        {
            m_privateType.SetStaticField("STATIC_STRING", value);
        }
    }

    internal int memberVar    {
        get
        {
            int ret = ((int)(m_privateObject.GetField("memberVar")));
            return ret;
        }
        set
        {
            m_privateObject.SetField("memberVar", value);
        }
    }

    internal int PrivateMethodName(int paramName)
    {
        object[] args = new object[] {
            paramName};
        int ret = (int)(m_privateObject.Invoke("PrivateMethodName", new System.Type[] {
                typeof(int)}, args)));
        return ret;
    }

في CodeProject، هناك مقال يناقش فترة وجيزة إيجابيات وسلبيات اختبار أساليب خاصة. ثم يقدم بعض التعليمات البرمجية انعكاس للوصول إلى وسائل خاصة (على غرار قانون يوفر ماركوس أعلاه). المسألة الوحيدة التي وجدتها مع العينة أن الرمز لا يأخذ بعين الاعتبار أساليب طاقتها.

ويمكنك العثور على المادة هنا:

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

ونعلن لهم internal، ومن ثم استخدام InternalsVisibleToAttribute للسماح لاختبار وحدة التجميع لرؤيتها.

وأنا لا تميل إلى استخدام توجيهات مترجم لأنها فوضى الأشياء بسرعة. طريقة واحدة للتخفيف من ذلك إذا كنت حقا في حاجة إليها لوضعها في فئة جزئية ويكون الإنشاء الخاصة بك تتجاهل هذا الملف .cs عندما جعل نسخة الانتاج.

يجب ألا تختبر الطرق الخاصة للتعليمات البرمجية الخاصة بك في المقام الأول.يجب أن تختبر "الواجهة العامة" أو واجهة برمجة التطبيقات (API)، وهي الأشياء العامة لفصولك الدراسية.واجهة برمجة التطبيقات (API) هي جميع الطرق العامة التي تعرضها للمتصلين الخارجيين.

والسبب هو أنه بمجرد البدء في اختبار الأساليب الخاصة والداخلية لفصلك، فإنك تقوم بربط تنفيذ فصلك (الأشياء الخاصة) باختباراتك.وهذا يعني أنه عندما تقرر تغيير تفاصيل التنفيذ، سيتعين عليك أيضًا تغيير اختباراتك.

يجب عليك لهذا السبب تجنب استخدام InternalsVisibleToAtrribute.

إليكم محادثة رائعة لإيان كوبر تتناول هذا الموضوع: إيان كوبر:TDD، أين حدث كل هذا الخطأ

في بعض الأحيان، قد يكون من الجيد اختبار التصريحات الخاصة.في الأساس، لدى المترجم طريقة عامة واحدة فقط:ترجمة (سلسلة OutputFileName، Params string[] sourceSFileNames ).أنا متأكد من أنك تفهم أنه سيكون من الصعب اختبار مثل هذه الطريقة دون اختبار كل الإعلانات "المخفية"!

لهذا السبب قمنا بإنشاء Visual T#:لتسهيل الاختبارات.إنها لغة برمجة .NET مجانية (متوافقة مع C# v2.0).

لقد أضفنا عامل التشغيل ".-".انها مجرد تتصرف مثل ". المشغل ، إلا أنه يمكنك أيضًا الوصول إلى أي إعلان خفي من اختباراتك دون تغيير أي شيء في مشروعك الذي تم اختباره.

قم بإلقاء نظرة على موقعنا على الانترنت: تحميل هو - هي مجانا.

لقد قال أنا مندهش لا أحد هذا بعد، ولكن الحل لقد استخدمت هو جعل أسلوب ثابت داخل الطبقة لاختبار نفسه. هذا يتيح لك الوصول إلى كل شيء القطاعين العام والخاص لاختبار مع.

وعلاوة على ذلك، في لغة البرمجة (مع قدرات OO، مثل بايثون، وروبي PHP)، يمكنك جعل اختبار الملف نفسه عند تشغيل. طريقة سريعة لطيفة من التأكد من التغييرات لم يكسر أي شيء. من الواضح أن هذا يجعل حل قابل للتطبيق لاختبار جميع الفصول الدراسية: مجرد تشغيل كل منهم. (يمكنك أيضا القيام بذلك في لغات أخرى مع رئيسي الفراغ الذي يمتد دائما تجاربها كذلك).

وأريد إنشاء مثال رمز واضح هنا والتي يمكنك استخدامها على أي فئة التي تريد اختبار الأسلوب الخاص.

في الاختبار الطبقة حالة تشمل فقط هذه الأساليب ومن ثم توظيفها على النحو المشار إليه.

  /**
   *
   * @var Class_name_of_class_you_want_to_test_private_methods_in
   * note: the actual class and the private variable to store the 
   * class instance in, should at least be different case so that
   * they do not get confused in the code.  Here the class name is
   * is upper case while the private instance variable is all lower
   * case
   */
  private $class_name_of_class_you_want_to_test_private_methods_in;

  /**
   * This uses reflection to be able to get private methods to test
   * @param $methodName
   * @return ReflectionMethod
   */
  protected static function getMethod($methodName) {
    $class = new ReflectionClass('Class_name_of_class_you_want_to_test_private_methods_in');
    $method = $class->getMethod($methodName);
    $method->setAccessible(true);
    return $method;
  }

  /**
   * Uses reflection class to call private methods and get return values.
   * @param $methodName
   * @param array $params
   * @return mixed
   *
   * usage:     $this->_callMethod('_someFunctionName', array(param1,param2,param3));
   *  {params are in
   *   order in which they appear in the function declaration}
   */
  protected function _callMethod($methodName, $params=array()) {
    $method = self::getMethod($methodName);
    return $method->invokeArgs($this->class_name_of_class_you_want_to_test_private_methods_in, $params);
  }

و$ هذا -> _ callMethod ( '_ someFunctionName، مجموعة (PARAM1، PARAM2، param3))؛

ومجرد إصدار المعلمات في الترتيب الذي تظهر في وظيفة خاصة الأصلية

لأي شخص يريد تشغيل أساليب خاصة دون جميع فيس والفوضى. هذا يعمل مع أي إطار وحدة اختبار باستخدام أي شيء ولكن التفكير القديمة الجيدة.

public class ReflectionTools
{
    // If the class is non-static
    public static Object InvokePrivate(Object objectUnderTest, string method, params object[] args)
    {
        Type t = objectUnderTest.GetType();
        return t.InvokeMember(method,
            BindingFlags.InvokeMethod |
            BindingFlags.NonPublic |
            BindingFlags.Instance |
            BindingFlags.Static,
            null,
            objectUnderTest,
            args);
    }
    // if the class is static
    public static Object InvokePrivate(Type typeOfObjectUnderTest, string method, params object[] args)
    {
        MemberInfo[] members = typeOfObjectUnderTest.GetMembers(BindingFlags.NonPublic | BindingFlags.Static);
        foreach(var member in members)
        {
            if (member.Name == method)
            {
                return typeOfObjectUnderTest.InvokeMember(method, BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.InvokeMethod, null, typeOfObjectUnderTest, args);
            }
        }
        return null;
    }
}

وبعد ذلك في الاختبارات الفعلية الخاصة بك، يمكنك أن تفعل شيئا من هذا القبيل:

Assert.AreEqual( 
  ReflectionTools.InvokePrivate(
    typeof(StaticClassOfMethod), 
    "PrivateMethod"), 
  "Expected Result");

Assert.AreEqual( 
  ReflectionTools.InvokePrivate(
    new ClassOfMethod(), 
    "PrivateMethod"), 
  "Expected Result");

وMbUnit حصلت على المجمع لطيفة لهذا تسمى العاكس.

Reflector dogReflector = new Reflector(new Dog());
dogReflector.Invoke("DreamAbout", DogDream.Food);

ويمكنك أيضا تعيين والحصول على قيم من خصائص

dogReflector.GetProperty("Age");

وفيما يتعلق "اختبار الخاص" أوافق على أن .. في عالم مثالي. لا يوجد أي نقطة في القيام الاختبارات وحدة خاصة. ولكن في العالم الحقيقي الذي قد ينتهي الرغبة في كتابة الاختبارات خاصة بدلا من التعليمات البرمجية إعادة بيع ديون.

المادة عن وحدة اختبار أساليب خاصة. ولكن لست متأكدا ما هو أفضل، لجعل لكم والتطبيق المصممة خصيصا لاختبار (انها مثل خلق تجارب لاختبار فقط) أو استخدام انعكاس للاختبار. جميلة بالتأكيد معظمنا سوف نختار الطريقة الثانية.

PrivateObject صف دراسي. ولكن كما ذكرت سابقا أفضل لتجنب اختبار أساليب خاصة.

Class target = new Class();
PrivateObject obj = new PrivateObject(target);
var retVal = obj.Invoke("PrivateMethod");
Assert.AreEqual(retVal);
CC -Dprivate=public

و"CC" هو خط مترجم الأوامر على نظام I استخدامها. -Dfoo=bar يفعل ما يعادل #define foo bar. لذلك، هذا الخيار تجميع تتغير بشكل فعال جميع الاشياء الخاصة للجمهور.

وهنا مثال، لأول مرة توقيع الأسلوب:

private string[] SplitInternal()
{
    return Regex.Matches(Format, @"([^/\[\]]|\[[^]]*\])+")
                        .Cast<Match>()
                        .Select(m => m.Value)
                        .Where(s => !string.IsNullOrEmpty(s))
                        .ToArray();
}

وهنا الاختبار:

/// <summary>
///A test for SplitInternal
///</summary>
[TestMethod()]
[DeploymentItem("Git XmlLib vs2008.dll")]
public void SplitInternalTest()
{
    string path = "pair[path/to/@Key={0}]/Items/Item[Name={1}]/Date";
    object[] values = new object[] { 2, "Martin" };
    XPathString xp = new XPathString(path, values);

    PrivateObject param0 = new PrivateObject(xp);
    XPathString_Accessor target = new XPathString_Accessor(param0);
    string[] expected = new string[] {
        "pair[path/to/@Key={0}]",
        "Items",
        "Item[Name={1}]",
        "Date"
    };
    string[] actual;
    actual = target.SplitInternal();
    CollectionAssert.AreEqual(expected, actual);
}

وهناك طريقة للقيام بذلك هو أن تكون طريقة protected والكتابة لاعبا اساسيا الاختبار الذي يرث صفك لفحصها. بهذه الطريقة، كنت ولا تحول طريقة public، ولكنك تمكين الاختبار.

1) إذا كان لديك رمز قديم، فإن الطريقة الوحيدة لاختبار الأساليب الخاصة هي عن طريق التفكير.

2) إذا كان الرمز جديدًا، فلديك الخيارات التالية:

  • استخدم الانعكاس (للتعقيد)
  • اكتب اختبار وحدة في نفس الفئة (يجعل رمز الإنتاج قبيحًا من خلال إجراء رمز الاختبار أيضًا)
  • قم بإعادة بناء الطريقة وجعلها عامة في نوع ما من فئات الاستخدام
  • استخدم التعليق التوضيحي @VisibleForTesting وقم بإزالة الخاص

أفضّل طريقة التعليق التوضيحي، فهي الأبسط والأقل تعقيدًا.المشكلة الوحيدة هي أننا قمنا بزيادة الرؤية والتي أعتقد أنها لا تشكل مصدر قلق كبير.يجب أن نقوم دائمًا بالتشفير إلى الواجهة، لذلك إذا كان لدينا واجهة MyService وتطبيق MyServiceImpl، فيمكننا الحصول على فئات الاختبار المقابلة وهي MyServiceTest (طرق واجهة الاختبار) وMyServiceImplTest (طرق الاختبار الخاصة).يجب على جميع العملاء على أي حال استخدام الواجهة، لذلك على الرغم من زيادة رؤية الطريقة الخاصة، فلا ينبغي أن يكون ذلك مهمًا حقًا.

ويمكنك أيضا أن نعلن بأنها الجمهور أو داخلية (مع InternalsVisibleToAttribute)، في حين بناء في تصحيح وضع:

    /// <summary>
    /// This Method is private.
    /// </summary>
#if DEBUG
    public
#else
    private
#endif
    static string MyPrivateMethod()
    {
        return "false";
    }

ووينفخ رمز، ولكن سيتم private في إنشاء إصدار.

في رأيي يجب أن حدة فقط اختبار API العام كلاسي الخاص بك.

وجعل الجمهور طريقة، من أجل وحدة اختبار ذلك، فواصل التغليف تعريض تفاصيل التنفيذ.

وA API الصالح العام يحل هدفا الفوري للرمز العميل ويحل هذا الهدف تماما.

، وأضاف

هل يمكن أن تولد طريقة الاختبار للأسلوب خاص من Visual استوديو 2008. عند إنشاء وحدة الاختبار لطريقة الخاص مجلد اختبار المراجع إلى مشروع اختبار ويضاف إلى استرجاع إلى هذا المجلد. ويشار إلى استرجاع إلى ذلك أيضا في منطق طريقة وحدة الاختبار. هذا يسمح استرجاع اختبار وحدتك لاستدعاء أساليب خاصة في التعليمات البرمجية التي تختبره. للحصول على تفاصيل إلقاء نظرة على

http://msdn.microsoft.com/en-us/library /bb385974.aspx

لاحظ أيضا أن InternalsVisibleToAtrribute لديه شرط أن يكون التجميع الخاص بك <لأ href = "http://msdn.microsoft.com/en-us/library/bb385840٪28v=vs.90٪29.aspx" يختلط = "نوفولو noreferrer"> اسمه قوية، مما يخلق انها مجموعة الخاصة من المشاكل إذا كنت تعمل في الحل الذي لم يكن لديه هذا الشرط من قبل. يمكنني استخدام استرجاع لاختبار أساليب خاصة. انظر هذا السؤال أن للحصول على مثال على ذلك.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top