testValidateConfigLehntLeereFelderAb(); $this->testValidateConfigLiefertPflichtfelder(); $this->testAccountId(); $this->testApplyAccountFilter(); } private function makeService(array $source): FinTsFetchService { return new FinTsFetchService($source, function (string $msg): void { // Logs werden in diesem Test nicht ausgewertet. }); } private function callPrivate(object $obj, string $method, array $args = []): mixed { $ref = new \ReflectionMethod($obj, $method); $ref->setAccessible(true); return $ref->invokeArgs($obj, $args); } private function testValidateConfigLehntLeereFelderAb(): void { $base = [ 'id' => 1, 'provider_name' => 'Testbank', 'blz' => '12345678', 'benutzerkennung' => 'user', 'pin' => 'geheim', 'fints_url' => 'https://example.test/fints', ]; foreach (['blz', 'benutzerkennung', 'pin', 'fints_url'] as $missingField) { $source = $base; $source[$missingField] = ''; $svc = $this->makeService($source); $result = $this->callPrivate($svc, 'validateConfig'); $this->assert($result === null, "validateConfig() lehnt leeres Feld '{$missingField}' ab"); } } private function testValidateConfigLiefertPflichtfelder(): void { $source = [ 'id' => 1, 'provider_name' => 'Testbank', 'blz' => '12345678', 'benutzerkennung' => 'user', 'pin' => 'geheim', 'fints_url' => 'https://example.test/fints', ]; $svc = $this->makeService($source); $result = $this->callPrivate($svc, 'validateConfig'); $this->assertEquals( ['blz' => '12345678', 'user' => 'user', 'pin' => 'geheim', 'url' => 'https://example.test/fints'], $result, 'validateConfig() liefert die getrimmten Pflichtfelder bei vollständiger Konfiguration' ); } private function testAccountId(): void { $ref = new \ReflectionMethod(FinTsFetchService::class, 'accountId'); $ref->setAccessible(true); $withIban = new class { public function getIban(): string { return 'DE02120300000000202051'; } public function getAccountNumber(): string { return '000000202051'; } }; $this->assertEquals( 'DE02120300000000202051', $ref->invoke(null, $withIban), 'accountId() nutzt die IBAN, wenn vorhanden' ); $withoutIbanNoSub = new class { public function getIban(): string { return ''; } public function getAccountNumber(): string { return '4711'; } }; $this->assertEquals( 'AN:4711:', $ref->invoke(null, $withoutIbanNoSub), 'accountId() baut ohne IBAN einen AN:-Identifier aus der Kontonummer' ); $withoutIbanWithSub = new class { public function getIban(): string { return ''; } public function getAccountNumber(): string { return '4711'; } public function getSubAccount(): string { return '01'; } }; $this->assertEquals( 'AN:4711:01', $ref->invoke(null, $withoutIbanWithSub), 'accountId() hängt die Unterkontonummer an, wenn vorhanden' ); } private function testApplyAccountFilter(): void { $accA = new class { public function getIban(): string { return 'DE02120300000000202051'; } public function getAccountNumber(): string { return '000000202051'; } }; $accB = new class { public function getIban(): string { return 'DE11500105170648489890'; } public function getAccountNumber(): string { return '0648489890'; } }; // Leere Filterliste → kein Konto entspricht der Auswahl $svc = $this->makeService(['id' => 1, 'account_filter' => '[]']); $result = $this->callPrivate($svc, 'applyAccountFilter', [[$accA, $accB]]); $this->assertEquals([], $result, 'applyAccountFilter() mit leerer Filterliste liefert keine Konten'); // Passender Filter → nur das gefilterte Konto $svc = $this->makeService(['id' => 1, 'account_filter' => json_encode(['DE02120300000000202051'])]); $result = $this->callPrivate($svc, 'applyAccountFilter', [[$accA, $accB]]); $this->assertEquals(1, count($result), 'applyAccountFilter() mit passendem Filter liefert genau ein Konto'); $this->assert(($result[0] ?? null) === $accA, 'applyAccountFilter() liefert das gefilterte Konto A'); // Nicht passender Filter → kein Konto entspricht der Auswahl $svc = $this->makeService(['id' => 1, 'account_filter' => json_encode(['DE00000000000000000000'])]); $result = $this->callPrivate($svc, 'applyAccountFilter', [[$accA, $accB]]); $this->assertEquals([], $result, 'applyAccountFilter() mit nicht passendem Filter liefert keine Konten'); } }