[英]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.