簡體   English   中英

如何在PHPUnit測試中覆蓋Laravel的異常處理程序?

[英]How can I override Laravel's exception handler in PHPUnit tests?

我正在開發一個包含控制器的Laravel軟件包,我希望對其進行單元測試。 問題是如果在其中一個控制器中拋出異常,Laravel的異常處理程序會捕獲它並輸出500 HTTP響應。 PHPUnit不是更明智的,測試根本無法滿足200 OK斷言。 PHPUnit輸出中缺少堆棧跟蹤本地和Travis CI等服務都極大地阻礙了工作流程。

我知道我可以從諸如\\App\\Exceptions\\Handler地方重新拋出異常,但由於這是一個包,我無法修改那些應用程序文件( laravel/laravel只是一個依賴於測試,以便用於測試控制器的必要組件中的繩索)。

set_exception_handler()以為TestCase下面的set_exception_handler()調用會起作用,但奇怪的是它沒有任何影響:

public function createApplication()
{
    $app = require __DIR__.'/../bootstrap/app.php';

    $app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();

    set_exception_handler(function ($e) {
        throw $e;
    });

    return $app;
}

誰能告訴我為什么以上不起作用?

單元測試應該測試單個單元,而不是整個應用程序。

您很有可能正在進行功能或集成測試。

當您測試控制器並期望200響應時,您需要知道的一切都是響應代碼。 500響應未通過測試,表示故障或配置錯誤。 CI工具應該只顯示通過/失敗測試的數量。

測試不是調試,不應提供任何特殊的回溯。 如果您認為自己沒有足夠的有關錯誤性質的信息,則應該檢查錯誤處理和日志記錄。 否則,當生產中發生錯誤時,您將面臨缺乏信息的同樣問題。

您嘗試重置您所執行的異常處理程序將無法正常工作(正如您已經發現的那樣)。 當您使用call()方法發出請求時,Laravel會創建一個Http Kernel的新實例,當它處理新請求時,它會自行引導並運行HandleExceptions引導程序,這當然會再次重置異常處理程序。

您可能無權修改\\App\\Exceptions\\Handler類,但您不需要。 您需要做的就是創建自己的異常處理程序,然后更新IoC容器中的綁定以使用異常處理程序,而不是Laravel應用程序提供的異常處理程序。

首先,創建新的異常處理程序:

<?php

class MyExceptionHandler extends \App\Exceptions\Handler
{
    public function render($request, \Exception $e)
    {
        // You may want to keep all these cases for special exceptions.
        // If not, just get rid of these lines.
        $e = $this->prepareException($e);

        if ($e instanceof HttpResponseException) {
            return $e->getResponse();
        } elseif ($e instanceof AuthenticationException) {
            return $this->unauthenticated($request, $e);
        } elseif ($e instanceof ValidationException) {
            return $this->convertValidationExceptionToResponse($e, $request);
        }

        // Not a special exception. Just re-throw it to get meaningful output.
        throw $e;
    }
}

現在,在createApplication()方法中,更新異常處理程序綁定:

public function createApplication()
{
    $app = require __DIR__.'/../bootstrap/app.php';

    // Tell the tests to use your exception handler.
    $app->singleton(\Illuminate\Contracts\Debug\ExceptionHandler::class, MyExceptionHandler::class);

    $app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();

    return $app;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM