ReponseStandard = new stdClass(); $soapResponse->ReponseStandard->Resultat = true; $soapResponse->ReponseSpecifique = new stdClass(); $soapResponse->ReponseSpecifique->NbBovins = 2; $message = new stdClass(); $message->SortiesPresumees = new stdClass(); $message->SortiesPresumees->SortiePresumee = [ $this->makeExit('FR111', '2026-02-15'), $this->makeExit('FR222', null), ]; $dto = new PresumedExitsMapper(new StandardResponseMapper())->map($soapResponse, $message); self::assertInstanceOf(PresumedExitsDto::class, $dto); self::assertSame(2, $dto->nbBovins); self::assertCount(2, $dto->presumedExits); self::assertSame('FR111', $dto->presumedExits[0]->bovin?->nationalNumber); self::assertEquals(new DateTimeImmutable('2026-02-15'), $dto->presumedExits[0]->exitDate); self::assertNull($dto->presumedExits[1]->exitDate); } public function testMapWithoutMessageReturnsEmpty(): void { $soapResponse = new stdClass(); $soapResponse->ReponseStandard = new stdClass(); $soapResponse->ReponseStandard->Resultat = true; $soapResponse->ReponseSpecifique = new stdClass(); $soapResponse->ReponseSpecifique->NbBovins = 0; $dto = new PresumedExitsMapper(new StandardResponseMapper())->map($soapResponse, null); self::assertSame(0, $dto->nbBovins); self::assertSame([], $dto->presumedExits); } private function makeExit(string $nationalNumber, ?string $exitDate): object { $node = new stdClass(); $node->Bovin = new stdClass(); $node->Bovin->CodePays = 'FR'; $node->Bovin->NumeroNational = $nationalNumber; if (null !== $exitDate) { $node->DateSortie = $exitDate; } return $node; } }