Autofixture: يتهم Readonly بخاصية ليست للقراءة فقط

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

في طبقة المجال الخاص بي ، يوجد الفصل:

public class Telefone : IEntity
{
    public virtual int Id { get; protected internal set; }
    public virtual string Tipo { get; set; }
    public virtual string Numero { get; set; }
}

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

لذلك في طبقة المجال الخاصة بي تمت إضافة السمة في AssemblyInfo.cs:

[assembly: InternalsVisibleTo("MyTestLayer")]

سيسمح لي هذا بتعيين المعرف في طبقة الاختبارات ولكن ليس في طبقة المجال!

في طبقة الاختبار
هاتف جديد (). المعرف = 1 ؛ // يعمل !!

في طبقة واجهة المستخدم
هاتف جديد (). المعرف = 1 ؛ // غير مترجم! لا يعمل!

مشكلة

var pessoa = fix.Build<Pessoa>()
    .With(p => p.Nome)
    .Do((pess) =>
    {
        fix.Build<Telefone>()
            .With(p => p.Id)
            .With(p => p.Tipo)
            .With(p => p.Numero)
            .OmitAutoProperties()
            .CreateMany(10).ToList().ForEach(pess.Telefones.Add);

        fix.Build<Email>()
            .With(p => p.Id)
            .With(p => p.Tipo)
            .With(p => p.Endereco)
            .OmitAutoProperties()
            .CreateMany(10).ToList().ForEach(pess.Emails.Add);
    })
    .OmitAutoProperties()
    .Create();

نظريًا ، يجب أن يعمل الكود أعلاه ، ولكن عندما يحدث خطأ في اختبار الطريق الخاص بي:

الخاصية "Id" للقراءة فقط.

جميع الخصائص Id s هي protected internal .

في نفس الملف ، يمكن للاختبار نفسه القيام بشيء مثل:

هاتف جديد (). المعرف = 1 ؛ // يعمل !!
بريد إلكتروني جديد (). المعرف = 1 ؛ // يعمل !!

question

ال 4 كومينتر

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

تخبرك هذه المشكلة بالذات أن نموذج المجال الخاص بك _not_ قابل لإعادة الاستخدام.

لا يؤثر InternalsVisibleTo لأنه يسمح فقط بالوصول إلى مكتبة الاختبار الخاصة بك ، ولكن AutoFixture عبارة عن تجميع مختلف تمامًا. يخبرك هذا فقط أن _لا _ أي عميل آخر سيتمكن من إعادة استخدام نموذج المجال الخاص بك.

أفضل مسار للعمل هو إعادة النظر في تصميم API الخاص بك. عادة ، أفعل شيئًا كهذا:

ج #
فئة عامة Telefone: IEntity
{
هاتف عمومي (معرف int)
{
this.Id = معرف ؛
}

public virtual int Id { get; private set; }
public virtual string Tipo { get; set; }
public virtual string Numero { get; set; }

}
""

أثار هذا الكثير من النقاش في مجموعة الهندسة المعمارية التي أتبعها.
هناك مشكلة كبيرة في هذا النهج:

  1. المسؤول عن إنشاء المعرّف هو قاعدة البيانات ، ولا يتم إنشاؤه إلا عند حفظ الكائن.
  2. عندما أقوم بإنشاء كائن جديد ، أي معرف يجب أن يمر في المنشئ؟ لا يمكنني وضع المعرف في المنشئ.
  3. المعرف هو متسلسل int. طبقة المستودع هي أقرب طبقة في المجال. لإنشاء المعرّف ، سيفعل شيئًا مثل max (id) + 1 ثم قم بتعيين معرف الكائن الخاص بي. ولكن كيف يمكن ضبط المعرف إذا كان للقراءة فقط؟
  4. الطريقة الوحيدة لتعيين معرف في خاصية ReadOnly هي داخل الفئة نفسها أو باستخدام وكيل / انعكاس

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

  1. لماذا يجب على قاعدة البيانات تعيين معرفات؟ الشرط الوحيد هو أن يكون المعرف فريدًا. لهذا السبب لدينا GUIDs.
  2. قم بتمرير مثيل دليل جديد إلى المنشئ.
  3. لماذا المعرف تسلسلي؟ نادرًا ما يكون هناك أي سبب هندسي يجعل المعرفات متسلسلة.
  4. متفق. هناك سبب لوجود مُعدِّلات الوصول.

أنا أفهم المشكلة. لا أستطيع تغيير نوع PKs إلى Guid ، فربما يعمل حقًا.

أفهم الآن أن المشكلة لا تتعلق بالتركيب التلقائي ، ولكن إذا كنت مهتمًا. أقوم بإنشاء مشروع نموذج لمناقشة هذا.

شكرا.

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

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

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

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

ploeh picture ploeh  ·  3تعليقات

Ephasme picture Ephasme  ·  3تعليقات

gtbuchanan picture gtbuchanan  ·  3تعليقات