2

私は、すべての例外がエラー ハンドラーによってキャッチされ、RESTFul API に適した適切な JSON エラー応答で返される内部フレームワークを使用しています。

次に、一連のテスト (API テスト) を用意しました。主に、API が予想されるエラー コードを含む適切な JSON 応答を返すことをテストします。

すべてのテストで、グローバル変数が変更 (および復元) され、異なる HTTP 要求がエミュレートされます。(Guzzle などを使用して) cURL テストを実行することによる過負荷を回避するために、そのようにしています。CLI 環境では、コードがサーバーの URL を認識していません。

<?php
// ... example, part of a base ApiTestCase class:

// Override globals (should be backed up by PHPUnit)
$_SERVER['REQUEST_METHOD']     = $request->method;
$_SERVER['QUERY_STRING']       = http_build_query($request->parameters);
$_SERVER['PATH_INFO']          = $request->path;
$_SERVER['REQUEST_URI']        = $request->path . ($_SERVER['QUERY_STRING'] ? '?' : '') . $_SERVER['QUERY_STRING'];
$_SERVER['REQUEST_TIME']       = time();
$_SERVER['REQUEST_TIME_FLOAT'] = microtime(true);
$_SERVER['HTTP_COOKIE']        = '';

// Set headers, cookies and parameters
foreach ($request->headers as $k => $v) {
  $_SERVER['HTTP_' . strtoupper(str_replace('-', '_', trim($k)))] = $v;
}
if ($_SERVER['HTTP_COOKIE']) {
  $GLOBALS['_COOKIE'] = http_parse_cookie($_SERVER['HTTP_COOKIE']);
} else {
  $GLOBALS['_COOKIE'] = [];
}
$GLOBALS['_REQUEST'] = $request->parameters;

$responseBody = $app->start();

$response->httpCode = http_response_code();
$response->body     = $responseBody ? @json_decode($responseBody) : null;
$response->headers  = headers_list();

(この方法でグローバルを変更するのは良くないことはわかっています。また、フレームワークはグローバルに直接依存すべきではありませんが、それでもレガシー コードを処理する必要があります。)

ここで問題が発生します。JSON エラー応答をテストしようとすると、PHPUnit はスローされた例外を (冒頭で述べたハンドラーの前に) インターセプトするため、フレームワークはそれを JSON に変換して適切な応答を返す機会がありません。

PHPUnit マニュアルで何かを見つけて、PHPUnit エラー ハンドラを無効にしようとしましたが、うまくいきませんでした。

この場合、どうすればよいですか?ありがとう

4

3 に答える 3

0

明確にするために、ここで実際に例外をキャッチすることについて話しているわけではないようです。set_error_handler()プログラムを終了させる前に致命的なエラーをインターセプトするためにPHP を使用することについて話しているのです。これにより、エラーとキャッチされていない例外の両方が処理されます。

できないことの 1 つは、これらのエラーと例外をエラー ハンドラー関数に渡すことです。すでにわかっているように、phpUnit はオーバーライドできない独自のエラー処理を行います (これは基本的なことなので)。 phpUnit の仕組み)。

あなたがしなければならないことは、予想される例外またはエラーの種類を phpUnit に伝えることです。エラーが発生するかどうかに応じて、テストが成功または失敗します。エラー ハンドラは実行しませんが、実際には実行する必要はありません。必要に応じて、その機能を個別にテストできます。エラー条件については、エラー ハンドラーが毎回正しい出力を生成することを確認する必要はありません。ハンドラーをトリガーするエラーが発生することだけを確認する必要があります。

@expectedException通常の PHP 例外の場合、次のように、テスト関数の上にphpUnit の注釈を使用できます。

/**
 * @expectedException YourExpectedExceptionClass
 */
function testThisWillThrowAnException() {
    ....
}

PHP コードが PHP エラー (つまり、例外ではなくエラー) を生成すると予想される場合は、同じ考え方を使用しますが、phpUnit はエラーのヘルパー クラス名を提供しますPHPUnit_Framework_Error。したがって、コードは次のようになります。

/**
 * @expectedException PHPUnit_Framework_Error
 */
function testThisWillProduceAPHPError() {
    ....
}

どちらの場合でも、予想されるエラー/例外が発生した場合、テストは成功します。

また、特定の例外メッセージとコードをテストすることもできます。これは、例外クラス自体が十分な情報ではなく、テストが意図したとおりに実行されたかどうかを判断するためのものです。詳細については、アノテーションの phpUnit マニュアル ページを参照してください。

于 2015-11-02T14:41:46.977 に答える
0

上記の例も正しいです。私はアサーションとして例外を提供するだけで、例外の動作に関する知識を提供します。

/**
 * @dataProvider fixturesProvider // its just example
 */
public function testDataIsWrong($fixtures)
{
    try
    {
        //Some Code
        $this->fail('Exception');
    }
    catch(Exception $ex)
    {
        $this->assertEquals($ex,'Exception');
    }
}

これにより、コードの可能性も提供され、誤ったデータまたは誤ったデータをテストして、それが正しくないと主張できます。

于 2015-11-04T12:19:40.370 に答える