Phpunit: غير مسموح بتسلسل "Closure"

تم إنشاؤها على ٢ يناير ٢٠١٢  ·  12تعليقات  ·  مصدر: sebastianbergmann/phpunit

على الرغم من أن عمليات الإغلاق $GLOBAL لم تعد متسلسلة منذ 01aa34783c9b19d39e568641f3f2dd0fc983b11a & # 352 a $GLOBAL المصفوفة التي تحتوي على إغلاق كقيمة ستظل تتسبب في ظهور الخطأ "تسلسل" غير مسموح بالإغلاق ".

$GLOBALS[] = array( 'foo' => function() { return 'bar'; }  );
typbug

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

لدي نفس رسالة الخطأ هذه عندما أقوم بإنشاء مثيل new MyRestClient() ، الذي يحتوي $this->client = new \GuzzleHttp\Client(); على $x=function(){}; في مُنشئ صفي. أعتقد أن عميل Guzzle يفعل شيئًا مشابهًا داخليًا. هذا يجعل من المستحيل إنشاء مثيل من داخل اختبار phpunit. أنا حزين جدًا الآن: تنهد:

ال 12 كومينتر

يبدو أن بعض الأشخاص يواجهون هذه المشكلة بمن فيهم أنا. http://stackoverflow.com/questions/4366592/symfony-2-doctrine-2-phpunit-3-5-serialization-of-closure-exception

حالة أخرى فهمت

 / * test.php * /
 يمتد اختبار الفصل الدراسي PHPUnit_Framework_TestCase
 {
 اختبار الوظيفة الإغلاق () {
 $ this-> assertEquals (1، 1)؛
 call_user_func (الوظيفة ($ a) {
 رمي استثناء جديد ("اختبار") ؛
 } ، 10) ؛
 $ this-> assertEquals (2، 2)؛
 }
 }

ثم قم بتشغيله في عملية العزل

 phpunit - اختبار عزل العملية. php

ستحصل عليه

 كان هناك خطأ واحد:
 1) phTest :: testClosure
 PHPUnit_Framework_Exception: PHP خطأ فادح: استثناء غير معلوم "استثناء" برسالة "غير مسموح بتسلسل" في -: 37
 تتبع المكدس:
 # 0 - (37): تسلسل (صفيف)
 # 1 - (123): __الوحدة_الوحدة_الوحدة_أخرى
 # 2 {main}
 ألقيت في - على الخط 37
 فشل!
 الاختبارات: 1 ، التأكيدات: 0 ، الأخطاء: 1.

كنت أواجه نفس المشكلة عند استخدام عزل العملية ، وللتغلب عليها أضفت __sleep to your testCase وقمت بتنظيف الإغلاق هناك. بالنسبة لي ، قمت بتخزين بعض النماذج في خصائص حقيبة الاختبار ، لذا فقد كان خطأي حقًا ، وآمل أن يساعد هذا شخصًا ما.

أواجه نفس المشكلة أيضًا ، ويمكنني تكرار المشكلة

طلبات السحب دائما موضع تقدير!

أعلم أنه كان قليلاً ، لكنني كنت خارج المشروع لفترة من الوقت. بالإضافة إلى تعليق tmilos ، يمكنني تكرار المشكلة إذا قمت

/* test.php */
class closureTest extends PHPUnit_Framework_TestCase
{
    function testClosure() {
        call_user_func(function($a) {
            throw new \Exception("test");
        });
    }
}

لاحظ عدم وجود وسيطة مقدمة في نهاية call_user_func . ينتج استثناء التسلسل من محاولة إجراء تسلسل لكائن PHPUnit_Framework_TestResult. يمكن العثور على محاولة التسلسل هذه في السطر 42 من PHPUnit/Framework/Process/TestCaseMethod.tpl.dist . الجزء المخالف من الكائن الذي سيتم تسلسله هو مرجع إغلاق في التسلسل الهرمي لتتبع الاستثناء الذي تم طرحه:

[1] => Array
    (
        [function] => {closure}
        [class] => Issue451Test
        [type] => ->
        [args] => Array
            (
            )

)

سؤالي إذن ، نظرًا لأن هذه هي المرة الأولى التي أقوم فيها بترقيع PHPUnit ، لا يكفي لتجريد الإغلاق أو تعديله ليكون غير ضار - والذي قد يتضمن استخدام Reflection بلا شك - هل هناك بعض أفضل طرق PHPUnit للتعامل مع هذا ؟ أي أفكار أو مدخلات على الأقل؟

أيضًا ، كتبت اختبارًا ضمن Regressions / GitHub. هل هذا مقبول؟

kunjalpopat ، في إشارة إلى مشكلتك ، فإن أول شيء أود التحقق منه هو الاستثناءات. عندما تكون في عملية عزل ، قد تمنحك الاستثناءات التي تم طرحها رسالة "Serialization of Closure". حاول تغليف رمز الاختبار الخاص بك في محاولة / التقاط ومعرفة ما إذا كان ذلك سيؤدي إلى حل المشكلة ، وإذا حدث ذلك ، فقد ترغب في النظر في تقليل تغطية المحاولة / الصيد حتى تجد منطقة المشكلة.

تكمن المشكلة في PHPUnit_Util_GlobalState::backupGlobals :

if ($key != 'GLOBALS' &&
    !in_array($key, $superGlobalArrays) &&
    !in_array($key, $blacklist) &&
    !$GLOBALS[$key] instanceof Closure) {  // <-- this is the problem
    self::$globals['GLOBALS'][$key] = serialize($GLOBALS[$key]);
}

لقد اختلقت بعض المساعد في PHPUnit_Util_GlobalState :

public static function checkIfThereIsClosureInIt($arr) {
    if ($arr instanceof Closure)
        return true;
    if (is_object($arr))
        $arr = get_object_vars($arr);
    if (is_array($arr))
        foreach ($arr as $x)
            if (PHPUnit_Util_GlobalState::checkIfThereIsClosureInIt($x))
                return true;
    return false;
}

وقمت بتغيير وظيفة backupGlobals قليلاً:

foreach (array_keys($GLOBALS) as $key) {
    if ($key != 'GLOBALS' &&
        !in_array($key, $superGlobalArrays) &&
        !in_array($key, $blacklist) &&
        !PHPUnit_Util_GlobalState::checkIfThereIsClosureInIt($GLOBALS[$key])
//        !$GLOBALS[$key] instanceof Closure
    ) {
        self::$globals['GLOBALS'][$key] = serialize($GLOBALS[$key]);
    }
}

يبدو أن هذا الإصدار يعمل (لم أعد ألاحظ هذا الاستثناء).
نظرًا لأنه تكراري ضد $ GLOBALS ، فيمكنه إعطاء بعض الحرارة الإضافية لوحدة المعالجة المركزية.

إصلاح الكود أعلاه من stafr أصلح مشكلات PHPunit التي كنت أواجهها مع استثناءات "Serialization of Closure". شكرا جزيلا!

لدي نفس رسالة الخطأ هذه عندما أقوم بإنشاء مثيل new MyRestClient() ، الذي يحتوي $this->client = new \GuzzleHttp\Client(); على $x=function(){}; في مُنشئ صفي. أعتقد أن عميل Guzzle يفعل شيئًا مشابهًا داخليًا. هذا يجعل من المستحيل إنشاء مثيل من داخل اختبار phpunit. أنا حزين جدًا الآن: تنهد:

مجرد إضافة خبرتي. في الأساس عندما تضع وظيفة أو فئة مجهولة كسمة لفئة الاختبار ، فإن phpunit ستطلق Serialization of 'Closure' is not allowed أو Serialization of 'class<strong i="6">@anonymous</strong>' is not allowed . لذلك ، إذا كنت بحاجة إلى استخدام وظيفة أو فئة مجهولة ، فتأكد من متغيرها لمرة واحدة ، وليس سمة فئة الاختبار.

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