true, 'redis' => true, 'rabbitmq' => true], ) { } public function checkPostgres(): bool { return $this->checks['postgres']; } public function checkRedis(): bool { return $this->checks['redis']; } public function checkRabbitMQ(): bool { return $this->checks['rabbitmq']; } public function checkAll(): array { return $this->checks; } } /** * @see Story 1.8 - T7: Health Check Endpoint */ #[CoversClass(HealthCheckController::class)] final class HealthCheckControllerTest extends TestCase { private function createController( ?InfrastructureHealthCheckerInterface $healthChecker = null, ): HealthCheckController { $healthChecker ??= new InfrastructureHealthCheckerStub(); return new HealthCheckController($healthChecker); } #[Test] public function itReturnsHealthyWhenAllServicesAreUp(): void { $controller = $this->createController(); $response = $controller(); self::assertSame(Response::HTTP_OK, $response->getStatusCode()); $data = json_decode($response->getContent(), true); self::assertSame('healthy', $data['status']); self::assertTrue($data['checks']['postgres']); self::assertTrue($data['checks']['redis']); self::assertTrue($data['checks']['rabbitmq']); } #[Test] public function itReturnsUnhealthyWhenPostgresIsDown(): void { $checker = new InfrastructureHealthCheckerStub([ 'postgres' => false, 'redis' => true, 'rabbitmq' => true, ]); $controller = $this->createController($checker); $response = $controller(); self::assertSame(Response::HTTP_SERVICE_UNAVAILABLE, $response->getStatusCode()); $data = json_decode($response->getContent(), true); self::assertSame('unhealthy', $data['status']); self::assertFalse($data['checks']['postgres']); } #[Test] public function itIncludesTimestampInResponse(): void { $controller = $this->createController(); $response = $controller(); $data = json_decode($response->getContent(), true); self::assertArrayHasKey('timestamp', $data); self::assertMatchesRegularExpression( '/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+[+-]\d{2}:\d{2}$/', $data['timestamp'], ); } #[Test] public function itReturnsAllServiceChecks(): void { $controller = $this->createController(); $response = $controller(); $data = json_decode($response->getContent(), true); self::assertArrayHasKey('postgres', $data['checks']); self::assertArrayHasKey('redis', $data['checks']); self::assertArrayHasKey('rabbitmq', $data['checks']); } #[Test] public function itReturnsUnhealthyWhenRabbitmqIsDown(): void { $checker = new InfrastructureHealthCheckerStub([ 'postgres' => true, 'redis' => true, 'rabbitmq' => false, ]); $controller = $this->createController($checker); $response = $controller(); self::assertSame(Response::HTTP_SERVICE_UNAVAILABLE, $response->getStatusCode()); $data = json_decode($response->getContent(), true); self::assertFalse($data['checks']['rabbitmq']); } #[Test] public function itReturnsUnhealthyWhenRedisIsDown(): void { $checker = new InfrastructureHealthCheckerStub([ 'postgres' => true, 'redis' => false, 'rabbitmq' => true, ]); $controller = $this->createController($checker); $response = $controller(); self::assertSame(Response::HTTP_SERVICE_UNAVAILABLE, $response->getStatusCode()); $data = json_decode($response->getContent(), true); self::assertFalse($data['checks']['redis']); } }