Laravel使用Pest测试生产环境触发Sentry的中间件代码覆盖问题
解决Laravel中间件Sentry告警分支的测试覆盖率问题
核心问题原因
测试默认运行在testing环境,导致config('app.env') === 'production'条件不成立,无法进入目标分支统计覆盖率。
解决步骤
1. 临时切换测试环境为production
在测试方法中,通过config()->set()临时修改环境配置,确保条件判断触发:
// 测试方法开头设置环境为production config()->set('app.env', 'production');
2. 正确Mock Sentry的全局调用
直接调用\Sentry\captureException()会使用Sentry的全局Hub实例,需要将Mock对象绑定到Laravel容器中替换默认实例:
// Mock Sentry的HubInterface $sentryHub = Mockery::mock(\Sentry\State\HubInterface::class); // 验证捕获的异常是否符合预期(用参数约束替代硬匹配实例) $sentryHub->shouldReceive('captureException') ->once() ->with(Mockery::on(function ($exception) { return $exception->getMessage() === 'my message' && $exception->getCode() === 500; })); // 将Mock的Hub绑定到全局容器 app()->instance(\Sentry\State\HubInterface::class, $sentryHub);
3. 调整测试执行顺序
确保环境设置和Mock完成后,再发起请求:
public function test_sentry_alert_triggers_on_production_500() { // 1. 临时切换环境为production config()->set('app.env', 'production'); // 2. Mock Sentry Hub $sentryHub = Mockery::mock(\Sentry\State\HubInterface::class); $sentryHub->shouldReceive('captureException') ->once() ->with(Mockery::on(function ($exception) { return $exception->getMessage() === 'my message' && $exception->getCode() === 500; })); app()->instance(\Sentry\State\HubInterface::class, $sentryHub); // 3. 模拟接口返回500 Saloon::fake([ PostRequest::class => MockResponse::make(["message"=>"error"], 500), ]); // 4. 发起请求并断言响应 $responseData = ["message"=>"error"]; $this->postJson("/my_url", ['body' => 'test']) ->assertJson($responseData) ->assertStatus(500); }
4. 可选:测试后恢复环境
避免环境修改影响其他测试用例,可在tearDown中恢复配置:
protected function tearDown(): void { parent::tearDown(); config()->set('app.env', 'testing'); }
内容的提问来源于stack exchange,提问作者DeveloperX
相关产品推荐
相关产品推荐

