Autofixture: فشل إنشاء مثيل مخصص على المراجع الدائرية

تم إنشاؤها على ١٣ يناير ٢٠١٨  ·  5تعليقات  ·  مصدر: AutoFixture/AutoFixture

    [TestFixture]
    public class TestAutoFixture4
    {
        [Test]
        [AutoMoqData]
        public void CreatingAnDummyObjectShouldNotThrow(IFixture fixture)
        {
            fixture.Invoking(x => x.Create<DummyObject>()).ShouldNotThrow();
        }

        [Test]
        [AutoMoqData]
        public void BuildingAnDummyObjectShouldNotThrow(IFixture fixture)
        {
            fixture.Invoking(x => x.Build<DummyObject>().Create()).ShouldNotThrow();
        }
    }

    public class DummyObject
    {
        public Guid Id { get; set; }
        public DummyObject CircularRef { get; set; }
    }

    public class AutoMoqDataAttribute : AutoDataAttribute
    {
        public AutoMoqDataAttribute()
            : base(new Fixture()
                 .Customize(
                    new DummyCustomization()
                ))
        { }
    }

    public class DummyCustomization : ICustomization
    {
        public void Customize(IFixture fixture)
        {
            fixture.Customize<DummyObject>(c =>
                c.Without(x => x.CircularRef)
            );
        }
    }

تم للتو تحديث AutoFixture من 3.50.6 إلى 4.0.0.

يعمل الكود أعلاه بشكل مثالي على 3.50.6 ، ولكن الاختبار الأول فقط (باستخدام fixture.Create) يمر باستخدام 4.0.0 (.NET 4.6.2 ، NUnit3.7.1 ، FluentAssertions 4.19.4).

فشل الاختبار باستخدام fixture.Build ، حتى إذا كان التخصيص المحقون يحدد عدم حل المرجع الدائري.

هل فاتني شيء في التغيير أم أنه خطأ؟

شكرا لك مقدما :)

question

التعليق الأكثر فائدة

هل تعتقد أن نهج Omitter يمكن أن يحل المشكلة؟ لم أكن أعرف هذا الفصل وسأحاول بالتأكيد على أي حال.

إذا أعدت كتابة التخصيص الخاص بك على النحو التالي ، فستبدأ جميع الاختبارات بالنجاح:

c# public class DummyCustomization : ICustomization { public void Customize(IFixture fixture) { // Don't populate the DummyObject.CircularRef property. fixture.Customizations.Add( new Omitter( new EqualRequestSpecification( typeof(DummyObject).GetProperty(nameof(DummyObject.CircularRef))))); } }

لذلك ، نعم ، يجب أن يحل مشكلتك 😉 كما أن هذا النهج لا يبدو مرهقًا جدًا ، لذا يجب أن يكون مقبولًا.

يرجى إعلامي إذا كان لديك المزيد من الأسئلة حول سؤالك.

ال 5 كومينتر

@ Dev-I-Ant نشكرك على نشر المشكلة هنا وعلى هذا الوصف التفصيلي 👍

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

عندما تستخدم Build<T>() API ، فأنت في الواقع تنشئ تخصيصًا مؤقتًا للنوع DummyObject . هذا يعني أنه تم تجاهل جميع التخصيصات السابقة (المطبقة عبر واجهة برمجة التطبيقات Customize<DummyObject>() ) ولا تشارك. لهذا السبب ترى مرة أخرى خطأ حول التبعية الدائرية.

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


للتخفيف من المشكلة التي لاحظتها ، أرى طريقتين أساسيتين.

الحل 1: أضف Omitter للممتلكات

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

الحل 2: استخدم Create<T>() API بدلاً من ذلك

في عينتك ، ليست هناك حاجة لاستخدام واجهة برمجة تطبيقات Build<> . بالطبع ، قد تكون قد قدمت نموذجًا مبسطًا وأنت في الواقع بحاجة إلى واجهة برمجة التطبيقات هذه. ومع ذلك ، قررت أن أقدم لك هذا الخيار فقط في حالة 😃

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

zvirja شكرًا على

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

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

أرغب في تغيير النموذج ولكن هذا غير ممكن ، على الأقل في الوقت الحالي.

لذلك ، ببساطة إنشاء كائنات باستخدام تركيبات. لا يعد الإنشاء خيارًا وعادة ما نقوم ببنائها واستدعاء OmitAllProperties بعد ذلك مباشرة ، مما يحد من قوة التركيز البؤري التلقائي.

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

شكرًا مرة أخرى ، واسمحوا لي أن أعرف إذا كنت تعتقد أنه يمكنك إضافة شيء إلى تفكيري.

هل تعتقد أن نهج Omitter يمكن أن يحل المشكلة؟ لم أكن أعرف هذا الفصل وسأحاول بالتأكيد على أي حال.

إذا أعدت كتابة التخصيص الخاص بك على النحو التالي ، فستبدأ جميع الاختبارات بالنجاح:

c# public class DummyCustomization : ICustomization { public void Customize(IFixture fixture) { // Don't populate the DummyObject.CircularRef property. fixture.Customizations.Add( new Omitter( new EqualRequestSpecification( typeof(DummyObject).GetProperty(nameof(DummyObject.CircularRef))))); } }

لذلك ، نعم ، يجب أن يحل مشكلتك 😉 كما أن هذا النهج لا يبدو مرهقًا جدًا ، لذا يجب أن يكون مقبولًا.

يرجى إعلامي إذا كان لديك المزيد من الأسئلة حول سؤالك.

هذا يعمل بشكل مثالي. شكرا جزيلا! أعتقد أنه يمكنك إغلاق هذا بعد ذلك :)

@ Dev-I-Ant رائع ، شكرًا على ملاحظاتك! :)

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات

القضايا ذات الصلة

JoshKeegan picture JoshKeegan  ·  6تعليقات

zvirja picture zvirja  ·  4تعليقات

mjfreelancing picture mjfreelancing  ·  4تعليقات

josh-degraw picture josh-degraw  ·  4تعليقات

ecampidoglio picture ecampidoglio  ·  7تعليقات