Laravel - 编写一个测试用例来检查服务类触发的自定义异常是否通过渲染方法生成日志

问题描述 投票:0回答:1

在我的 Laravel 构建中,我有一个服务类:

use GuzzleHttp\Client;
use App\Services\ApiService\Exceptions\ServiceException

class ApiService {
    __construct(
        protected Client $client
    ) {
    }

    public function request() {

        try {
            $response = $this->client->get('/test');
        } catch (Exception $e) {
            throw new ServiceException($e->getMessage(), $e->getCode(), $e);
        }

        return response;
    }
}

我的自定义异常类

ServiceException
看起来像这样:

class ServiceException extends Exception {
    public function __construct($message, $code, $previous) {
        parent::__construct($message, $code, $previous);
    }

    public function report() {
        Log::error($this->getMessage());
    }
}

我编写了一个测试用例,尝试验证当

Log::error
抛出
ApiService::request
时是否调用
ServiceException

test_api_service_logs_error_when_request_fails() {
    $clientMock = new Client([
        'handler' => HandlerStack::create(
            new MockHandler([
                new Response(500, [], 'Internal Server Error')
            ])
        )
    ]);

    Log::shouldReceive('error')
        ->once()

    $service = new ApiService($clientMock);
    $service->request();
}

当我运行测试时,出现错误:

来自 Mockery_0_Illuminate_Log_LogManager 的方法 error() 应该叫

据我了解,Laravel 应该检测

ServiceException::report
方法并触发
Log::error
,但情况似乎并非如此。 Laravel 在测试期间和实际运行时的执行之间显然存在行为差异,如果有人能启发我,我将不胜感激!

编辑: 我还应该补充一点,我尝试在使用

withoutExceptionHandling()
调用路线时使用
$this->get('/api/my-route')
,但仍然没有接听
report()

php laravel testing logging phpunit
1个回答
0
投票

差异不在于 Laravel,而在于你对测试和异常的理解。

根据文档: https://laravel.com/docs/10.x/http-tests#exception-handling

assertThrows 方法可用于断言给定范围内的代码 闭包抛出指定类型的异常:

$this->assertThrows(
    fn () => (new ProcessOrder)->execute(),
    OrderInvalid::class
);

另请阅读

withoutExceptionHandling()
,其中指出:

有时您可能想测试您的应用程序是否抛出异常 具体异常。确保异常不会被捕获 通过 Laravel 的异常处理程序并作为 HTTP 响应返回,您 可以在进行之前调用 withoutExceptionHandling 方法 要求:

您也不需要测试 Laravel 的核心功能,因为这有点多余,因为您的异常正在处理日志记录。

你应该测试的是是否抛出异常。

test_api_service_logs_error_when_request_fails() {
    $clientMock = new Client([
        'handler' => HandlerStack::create(
            new MockHandler([
                new Response(500, [], 'Internal Server Error')
            ])
        )
    ]);

    $this->assertThrows(
        fn () => (new ApiService($clientMock))->request(),
        ServiceException::class
    );
}
© www.soinside.com 2019 - 2024. All rights reserved.