createMock(HttpClientInterface::class); $httpClient->expects(self::never())->method('request'); $service = new PontBasculeService($httpClient, $decoder, 'http://example.test', true); $result = $service->fetch(); self::assertSame(121, $result->getDsd()); self::assertSame(1420.0, $result->getWeight()); self::assertInstanceOf(DateTimeImmutable::class, $result->getWeighedAt()); } public function testFetchUsesHttpClientWhenNotBypass(): void { $payload = json_encode([ 'response_ascii' => "\u{0001}\u{0002}040200\u{0002}03000123.kg \u{0002}9900042", ], JSON_THROW_ON_ERROR); $response = $this->createMock(ResponseInterface::class); $response->expects(self::once())->method('getContent')->with(false)->willReturn($payload); $httpClient = $this->createMock(HttpClientInterface::class); $httpClient ->expects(self::once()) ->method('request') ->with('POST', 'http://example.test/send/dsd') ->willReturn($response) ; $decoder = new PontBasculePayloadDecoder(); $service = new PontBasculeService($httpClient, $decoder, 'http://example.test', false); $result = $service->fetch(); self::assertSame(42, $result->getDsd()); self::assertSame(123.0, $result->getWeight()); self::assertInstanceOf(DateTimeImmutable::class, $result->getWeighedAt()); } public function testFetchThrowsOnTransportFailure(): void { $exception = $this->createStub(TransportExceptionInterface::class); $httpClient = $this->createMock(HttpClientInterface::class); $httpClient ->expects(self::once()) ->method('request') ->willThrowException($exception) ; $decoder = new PontBasculePayloadDecoder(); $service = new PontBasculeService($httpClient, $decoder, 'http://example.test', false); $this->expectException(PontBasculeException::class); $this->expectExceptionMessage('Erreur lors de la communication avec le pont bascule:'); $service->fetch(); } public function testCheckHealthBypassIsHealthyWithoutHttpCall(): void { $httpClient = $this->createMock(HttpClientInterface::class); $httpClient->expects(self::never())->method('request'); $service = new PontBasculeService($httpClient, new PontBasculePayloadDecoder(), 'http://example.test', true); $health = $service->checkHealth(); self::assertTrue($health->isHealthy()); } public function testCheckHealthHealthyPayload(): void { $service = $this->serviceForHealthBody(json_encode([ 'ok' => true, 'busy' => false, 'port_connected' => true, 'port_error' => null, 'hostname' => 'liot-rasp-ferme-01', ], JSON_THROW_ON_ERROR)); $health = $service->checkHealth(); self::assertTrue($health->isHealthy()); self::assertSame('liot-rasp-ferme-01', $health->getHostname()); } public function testCheckHealthUnhealthyWhenPortError(): void { $service = $this->serviceForHealthBody(json_encode([ 'ok' => true, 'busy' => false, 'port_connected' => true, 'port_error' => 'device disconnected', ], JSON_THROW_ON_ERROR)); self::assertFalse($service->checkHealth()->isHealthy()); } public function testCheckHealthUnhealthyWhenPortNotConnected(): void { $service = $this->serviceForHealthBody(json_encode([ 'ok' => true, 'busy' => false, 'port_connected' => false, 'port_error' => null, ], JSON_THROW_ON_ERROR)); self::assertFalse($service->checkHealth()->isHealthy()); } public function testCheckHealthUnhealthyWhenBusy(): void { $service = $this->serviceForHealthBody(json_encode([ 'ok' => true, 'busy' => true, 'port_connected' => true, 'port_error' => null, ], JSON_THROW_ON_ERROR)); self::assertFalse($service->checkHealth()->isHealthy()); } public function testCheckHealthUnhealthyOnTransportFailure(): void { $httpClient = $this->createMock(HttpClientInterface::class); $httpClient ->expects(self::once()) ->method('request') ->willThrowException($this->createStub(TransportExceptionInterface::class)) ; $service = new PontBasculeService($httpClient, new PontBasculePayloadDecoder(), 'http://example.test', false); self::assertFalse($service->checkHealth()->isHealthy()); } public function testCheckHealthUnhealthyOnInvalidJson(): void { self::assertFalse($this->serviceForHealthBody('not-json')->checkHealth()->isHealthy()); } private function serviceForHealthBody(string $body): PontBasculeService { $response = $this->createStub(ResponseInterface::class); $response->method('getContent')->with(false)->willReturn($body); $httpClient = $this->createMock(HttpClientInterface::class); $httpClient ->expects(self::once()) ->method('request') ->with('GET', 'http://example.test/health') ->willReturn($response) ; return new PontBasculeService($httpClient, new PontBasculePayloadDecoder(), 'http://example.test', false); } }