$GLOBAL
クロージャーはシリアル化されなくなりましたが、01aa34783c9b19d39e568641f3f2dd0fc983b11a および #352 値としてクロージャーを含む$GLOBAL
配列は、「「許可されたクロージャー」のシリアル化エラー」が引き続き発生します。
$GLOBALS[] = array( 'foo' => function() { return 'bar'; } );
私はそれを取得している別のケース
/* test.php */ クラス closureTest は PHPUnit_Framework_TestCase を拡張します { 関数 testClosure() { $this->assertEquals(1, 1); call_user_func(関数($a) { 新しい \Exception("test") をスローします。 }、10); $this->assertEquals(2, 2); } }
そして、それをプロセス分離で実行します
phpunit --プロセス分離 test.php
あなたは得るでしょう
エラーが 1 件ありました: 1) phTest::testClosure PHPUnit_Framework_Exception: PHP 致命的なエラー: キャッチされていない例外 'Exception' とメッセージ 'Serialization of 'Closure' is not allowed' in -:37 スタックトレース: #0 -(37): シリアライズ(配列) #1 - (123): __phpunit_run_isolated_test() #2 {メイン} 投入 - 37行目 失敗! テスト: 1、アサーション: 0、エラー: 1。
プロセス分離を使用するときに同じ問題が発生していました。これを回避するために、testCaseに__sleepを追加し、そこでクロージャをクリーンアップしました。 私にとっては、テストケースのプロパティにいくつかのモックを保存していたので、本当に自分のせいでした。
私も同じ問題を抱えており、前述の問題@tmilos を再現できます。 このチケットが無効かどうかはわかりませんが、解決できれば幸いです。 必要に応じてプル リクエストを送信するつもりです。
プルリクエストはいつでも大歓迎です!
少し時間が経ったことは知っていますが、私はしばらくの間プロジェクトから外れていました。 @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 オブジェクトをシリアル化しようとしたために発生します。 このシリアル化の試みは、 PHPUnit/Framework/Process/TestCaseMethod.tpl.dist
42 行目にあります。 シリアル化されるオブジェクトの問題のある部分は、スローされた例外のトレース階層内のクロージャ参照です。
[1] => Array
(
[function] => {closure}
[class] => Issue451Test
[type] => ->
[args] => Array
(
)
)
PHPUnitにパッチを適用するのはこれが初めてなので、私の質問は、クロージャーを削除したり、それ以外の場合は無害になるように修正したりすることはできません.これには間違いなくReflectionの使用が含まれます. ? 少なくとも何か考えや入力はありますか?
また、Regressions/GitHub でテストを作成しました。 これは受け入れられますか?
@kunjalpopat 、あなたの問題に関して、私が最初に確認するのは例外です。 プロセス分離の場合、スローされた例外により、「Serialization of Closure」メッセージが表示される場合があります。 テスト コードを try/catch でラップして、問題が解決するかどうかを確認します。問題が解決する場合は、問題のある領域が見つかるまで try/catch の範囲を縮小することを検討することをお勧めします。
問題は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 に対する再帰であるため、CPU に余分な熱を与える可能性があります。
上記の stafr のコード修正により、「クロージャーのシリアル化」例外で発生していた PHPunit の問題が修正されました。 どうもありがとう!
new MyRestClient()
をインスタンス化するたびに、この同じエラー メッセージが表示されます。そのコンストラクターには$this->client = new \GuzzleHttp\Client();
が含まれます。 私のクラスのコンストラクターで$x=function(){};
を使用しようとしたときも同じです。 Guzzleクライアントは内部的に同様のことをしていると思います。 これにより、phpunitテスト内からインスタンス化することが不可能になります。 私は今とても悲しいです:sob:
私の経験を追加するだけです。 基本的に、匿名関数またはクラスをテスト クラス属性として配置すると、phpunit はSerialization of 'Closure' is not allowed
またはSerialization of 'class<strong i="6">@anonymous</strong>' is not allowed
をスローします。 したがって、匿名関数またはクラスを使用する必要がある場合は、クラス属性をテストするのではなく、その 1 回限りの変数を使用してください。
最も参考になるコメント
new MyRestClient()
をインスタンス化するたびに、この同じエラー メッセージが表示されます。そのコンストラクターには$this->client = new \GuzzleHttp\Client();
が含まれます。 私のクラスのコンストラクターで$x=function(){};
を使用しようとしたときも同じです。 Guzzleクライアントは内部的に同様のことをしていると思います。 これにより、phpunitテスト内からインスタンス化することが不可能になります。 私は今とても悲しいです:sob: