سؤال

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

أود أن أعرف الإجابة بلغة Java، لكن إذا كان هناك حل يتجاوز اللغات أود أن أعرفه.

رقم 2.في الجواب، هل سيتم مثل الإجابة الأخرى؟إذا كان الأمر كذلك، فسوف أقوم بوضع علامة على الإجابة الأخرى المقبولة أيضًا وأعيد صياغة سؤالي لمعالجة كل من المصنع حيث يتم إرجاع الواجهة وليس لديك أدنى فكرة عن نوع الفئة الملموسة التي نفذت الواجهة، والحالة التي تعرف فيها الفئة الملموسة مستخدم.

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

المحلول

نظرًا لأنني لا أعرف كيف تبدو طريقة المصنع الخاصة بك، فكل ما يمكنني أن أنصحك به الآن هو القيام بذلك

  1. تحقق لمعرفة أن الكائن هو التنفيذ الملموس الصحيح الذي كنت تبحث عنه:

    IMyInterface fromFactory = factory.create(...);  
    Assert.assertTrue(fromFactory instanceof MyInterfaceImpl1);
    
  2. يمكنك التحقق مما إذا كان المصنع قد قام بإعداد المثيلات الملموسة باستخدام متغيرات المثيلات الصالحة.

نصائح أخرى

ما تحاول القيام به ليس اختبار الوحدة

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

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

اختبار الوحدة على الكائنات بشكل عام

عند اختبار الوحدة، هناك أربعة أشياء تريد التأكيد عليها:

  1. قيم الإرجاع للاستعلامات (الطرق غير الفارغة) هي ما تتوقعه.
  2. تعمل الآثار الجانبية للأوامر (الطرق الفارغة) على تعديل الكائن نفسه كما تتوقعه.
  3. يتم تلقي الأوامر المرسلة إلى كائنات أخرى (يتم ذلك عادةً باستخدام نماذج وهمية).

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

مصانع اختبار الوحدة

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

نظرًا لأن المصانع لا تتغير بمرور الوقت (لأنها ستصبح حينها "بناة"، وهو نمط آخر)، فلا توجد أوامر للاختبار.

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

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

ملخص مصانع اختبار الوحدات

  1. لا تختبر السلوك ولا تفاصيل تنفيذ الكائنات التي تم إرجاعها!المصنع الخاص بك ليس مسؤولاً عن تنفيذ مثيلات الكائن!
  2. اختبار ما إذا كان قد تم استلام الأوامر المرسلة إلى التبعيات أم لا.

هذا كل شيء.إذا لم تكن هناك تبعيات، فلا يوجد شيء للاختبار.باستثناء ربما التأكيد على أن الكائن الذي تم إرجاعه ليس ملفًا null مرجع.

مصانع اختبار التكامل

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

لقد أجاب الآخرون هنا بالفعل عن كيفية القيام بذلك باستخدام instanceof المشغل أو العامل.

@cem-catikkas أعتقد أنه سيكون من الأصح مقارنة قيم getClass().getName().في حالة تصنيف فئة MyInterfaceImpl1 ضمن فئة فرعية، قد يتم كسر الاختبار الخاص بك، نظرًا لأن الفئة الفرعية هي مثيل لـ MyInterfaceImpl1.سأعيد الكتابة على النحو التالي:

IMyInterface fromFactory = factory.create(...);  
Assert.assertEquals(fromFactory.getClass().getName(), MyInterfaceImpl1.class.getName());

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

if (myNewObject instanceof CorrectClass)
{
    /* pass test */
}

تحديث:

لا أعرف لماذا تم وضع علامة على هذا، لذلك سأوسعه قليلاً ...

public void doTest()
{
    MyInterface inst = MyFactory.createAppropriateObject();
    if (! inst instanceof ExpectedConcreteClass)
    {
        /* FAIL */
    }
}

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

package it.sorintlab.pxrm.proposition.model.factory.task;

import org.junit.Test;

import java.util.Arrays;
import java.util.Collection;

import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;

import static org.junit.Assert.*;

@RunWith(Parameterized.class)
public class TaskFactoryTest {

    @Parameters
    public static Collection<Object[]> data() {
        return Arrays.asList(new Object[][] {
                { "sas:wp|repe" , WorkPackageAvailabilityFactory.class},
                { "sas:wp|people", WorkPackagePeopleFactory.class},
                { "edu:wp|course", WorkPackageCourseFactory.class},
                { "edu:wp|module", WorkPackageModuleFactory.class},
                { "else", AttachmentTaskDetailFactory.class}
        });
    }

    private String fInput;
    private Class<? extends TaskFactory> fExpected;

    public TaskFactoryTest(String input, Class<? extends TaskFactory> expected) {
        this.fInput = input;
        this.fExpected = expected;
    }

    @Test
    public void getFactory() {
        assertEquals(fExpected, TaskFactory.getFactory(fInput).getClass());
    }
}

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

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