سؤال

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

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

بمعنى آخر ، عبر MEF ، سيكون لدي شيء مثل

[Import]
public ICandyInterface ci { get; set; }

و

[Export(typeof(ICandyInterface))]
public class MyCandy : ICandyInterface
{
    [ImportingConstructor]
    public MyCandy( [Import("name_param")] string name) {}
    ...
}

لكن في اختبارات وحدتي ، أود فقط استخدام

CandyInterface MyCandy = new CandyInterface( "Godiva");

بالإضافة إلى ذلك ، تتطلب CandyInterface اتصالًا بقاعدة بيانات ، والتي عملت حولها بمجرد إضافة قاعدة بيانات اختبار إلى مجلد اختبار الوحدة الخاص بي ، ولديّ نونيت استخدام ذلك لجميع الاختبارات.

حسنًا ، ها هي أسئلتي بخصوص هذا الموقف:

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

المحلول

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

لا تحتاج إلى حاوية لتوصيل مثيلات في اختبارات الوحدة.

أوصي عمومًا بعدم تأليف التركيبات في الإعداد ، حيث يؤدي إلى التثبيت العام مكافحة النمط.

من الأفضل استبدال التبعيات مع اختبار الزوجي. تعتبر Dynamic Mocks واحدة من أكثر الطرق تنوعًا للقيام بذلك ، لذا بالتأكيد شيء يجب أن تتعلمه.

نصائح أخرى

أوافق على أن إنشاء المستندات يدويًا أفضل بكثير من استخدام حاوية تكوين MEF لتلبية الواردات ، ولكن فيما يتعلق بمذكرة "تركيبات التركيب في الإعداد يؤدي إلى النمط العام لمكافحة المباراة" - أريد أن أذكر أن هذا ليس هو الحال دائمًا.

إذا كنت تستخدم الحاوية الثابتة وتلبية الواردات عبر compositionInitializer.SatisfyImports ، فسيتعين عليك مواجهة النمط المضاد للتجهيزات العامة كتكوين inclizer.initialize لا يمكن استدعاء أكثر من مرة. ومع ذلك ، يمكنك دائمًا إنشاء CompositionContainer ، وإضافة كتالوجات ، واستدعاء SatisyImportonce على الحاوية نفسها. في هذه الحالة ، يمكنك استخدام CompositionContainer جديد في كل اختبار والابتعاد عن مواجهة النمط المضاد للثني المشترك/العام

قمت بالتدوين حول كيفية إجراء اختبارات الوحدة (وليس Nunit ولكنها تعمل بنفس الشيء) مع MEF. كانت الحيلة هي استخدام mockexportprovider وإنشاء قاعدة اختبار لجميع اختباراتي لترثها منها.

هذه هي وظيفتي الرئيسية التي تعمل في مجال التكامل واختبارات الوحدة:

protected void AutoWire(MockExportProvider mocksProvider, params Assembly[] assemblies){

CompositionContainer container = null;

var assCatalogs = new List<AssemblyCatalog>();

foreach(var a in assemblies)
{
    assCatalogs.Add(new AssemblyCatalog(a));
}

if (mocksProvider != null)
{
    var providers = new List<ExportProvider>();

    providers.Add(mocksProvider); //need to use the mocks provider before the assembly ones            

    foreach (var ac in assCatalogs)
    {
        var assemblyProvider = new CatalogExportProvider(ac);                    
        providers.Add(assemblyProvider);
    }

    container = new CompositionContainer(providers.ToArray());

    foreach (var p in providers) //must set the source provider for CatalogExportProvider back to the container (kinda stupid but apparently no way around this)
    {
        if (p is CatalogExportProvider)
        {
            ((CatalogExportProvider)p).SourceProvider = container;
        }
    }
}
else
{
    container = new CompositionContainer(new AggregateCatalog(assCatalogs));
}

container.ComposeParts(this);        
}

مزيد من المعلومات حول رسالتي: https://yoavniran.wordpress.com/2012/10/18/unit-testing-wcf--mef/

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