# Testing ## Setup - **Framework:** PHPUnit 11.5 - **Config:** `phpunit.xml` - **Bootstrap:** `tests/bootstrap.php` (PSR-4 autoloader for `Tests\` namespace) - **Run:** `composer test` → `vendor/bin/phpunit -c phpunit.xml --testdox` - **Helper:** `dg/bypass-finals` — allows mocking `final` classes ## PHPUnit Configuration ```xml ``` ## Test Files (`tests/Unit/`) | File | Subject | Coverage | |------|---------|---------| | `AllegroOrderImportServiceTest.php` | `AllegroOrderImportService` | Import, retry on 401, empty ID guard | | `AllegroShipmentServiceTest.php` | `AllegroShipmentService` | Shipment creation | | `AllegroStatusSyncServiceTest.php` | `AllegroStatusSyncService` | Status sync | | `AllegroTokenManagerTest.php` | `AllegroTokenManager` | Token refresh | | `ApaczkaShipmentServiceTest.php` | `ApaczkaShipmentService` | Apaczka API calls | | `AutomationServiceTest.php` | `AutomationService` | Email-once guard, condition evaluation | | `DeliveryStatusTest.php` | Delivery status mapping | Status translation | **No repository, controller, or view tests exist** — only service-layer unit tests. ## Test Patterns ### Mock Setup ```php final class AllegroOrderImportServiceTest extends TestCase { private AllegroIntegrationRepository&MockObject $integrationRepository; private AllegroApiClient&MockObject $apiClient; protected function setUp(): void { $this->apiClient = $this->createMock(AllegroApiClient::class); $this->service = new AllegroOrderImportService( $this->integrationRepository, $this->tokenManager, $this->apiClient, ... ); } } ``` ### Behavior Verification ```php $this->emailOnceRepository ->expects($this->exactly(2)) ->method('wasSent') ->willReturnOnConsecutiveCalls(false, true); $this->emailService ->expects($this->once()) ->method('send'); ``` ### Exception Testing ```php $this->expectException(AllegroApiException::class); $this->expectExceptionMessage('Podaj ID zamowienia'); $this->service->importSingleOrder(''); ``` ### Retry Logic Testing ```php $callCount = 0; $this->apiClient->method('getCheckoutForm') ->willReturnCallback(function () use (&$callCount): array { if (++$callCount === 1) { throw new RuntimeException('ALLEGRO_HTTP_401'); } return $payload; }); $this->service->importSingleOrder($id); $this->assertSame(2, $callCount); // retry happened ``` ### Test Data Builders ```php private function buildMinimalPayload(string $id): array { return [ 'id' => $id, 'status' => 'READY_FOR_PROCESSING', 'payment' => ['id' => 'pay-1', 'type' => 'allegro', ...], // all required nested fields ]; } ``` ## What Is Not Tested - Controllers (no HTTP integration tests) - Repositories (no DB integration tests — no test database configured) - Views (no rendering tests) - Cron handlers - Migration scripts ## Manual UAT Phase summaries note manual UAT steps after feature implementation (e.g., Phase 104 — Apaczka weekend delivery tested via UI). No documented UAT scripts or Postman collections.