From 8fb7781227274ed541b5eb65458a4da6d56eca8a Mon Sep 17 00:00:00 2001 From: Haylan Date: Tue, 7 Jul 2026 13:32:11 +0200 Subject: [PATCH] test(aggregator): cover concurrent fetch failure modes Mocks startFetch()/resolveFetch() instead of fetch(), and splits the old single failure test into separate start-throws and resolve-throws cases since those are now distinct call sites. --- .../Service/ContributionAggregatorTest.php | 47 +++++++++++++++---- 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/tests/Unit/Service/ContributionAggregatorTest.php b/tests/Unit/Service/ContributionAggregatorTest.php index b280626..61441f7 100644 --- a/tests/Unit/Service/ContributionAggregatorTest.php +++ b/tests/Unit/Service/ContributionAggregatorTest.php @@ -49,7 +49,7 @@ final class ContributionAggregatorTest extends TestCase { $provider = $this->createStub(ProviderInterface::class); $provider->method('isConfigured')->willReturn(true); - $provider->method('fetch')->willReturn(['2024-01-01' => 3]); + $provider->method('resolveFetch')->willReturn(['2024-01-01' => 3]); $aggregator = new ContributionAggregator([$provider], $this->logger); @@ -63,11 +63,11 @@ final class ContributionAggregatorTest extends TestCase { $providerA = $this->createStub(ProviderInterface::class); $providerA->method('isConfigured')->willReturn(true); - $providerA->method('fetch')->willReturn(['2024-01-01' => 3, '2024-01-02' => 1]); + $providerA->method('resolveFetch')->willReturn(['2024-01-01' => 3, '2024-01-02' => 1]); $providerB = $this->createStub(ProviderInterface::class); $providerB->method('isConfigured')->willReturn(true); - $providerB->method('fetch')->willReturn(['2024-01-01' => 2, '2024-01-03' => 5]); + $providerB->method('resolveFetch')->willReturn(['2024-01-01' => 2, '2024-01-03' => 5]); $aggregator = new ContributionAggregator([$providerA, $providerB], $this->logger); @@ -77,15 +77,15 @@ final class ContributionAggregatorTest extends TestCase } #[Test] - public function it_continues_fetching_remaining_providers_when_one_throws(): void + public function it_continues_fetching_remaining_providers_when_one_throws_on_start(): void { $failing = $this->createStub(ProviderInterface::class); $failing->method('isConfigured')->willReturn(true); - $failing->method('fetch')->willThrowException(new \RuntimeException('Network error')); + $failing->method('startFetch')->willThrowException(new \RuntimeException('Network error')); $healthy = $this->createStub(ProviderInterface::class); $healthy->method('isConfigured')->willReturn(true); - $healthy->method('fetch')->willReturn(['2024-01-01' => 7]); + $healthy->method('resolveFetch')->willReturn(['2024-01-01' => 7]); $aggregator = new ContributionAggregator([$failing, $healthy], $this->logger); @@ -95,14 +95,45 @@ final class ContributionAggregatorTest extends TestCase } #[Test] - public function it_logs_a_warning_when_a_provider_fetch_throws(): void + public function it_continues_fetching_remaining_providers_when_one_throws_on_resolve(): void + { + $failing = $this->createStub(ProviderInterface::class); + $failing->method('isConfigured')->willReturn(true); + $failing->method('resolveFetch')->willThrowException(new \RuntimeException('Network error')); + + $healthy = $this->createStub(ProviderInterface::class); + $healthy->method('isConfigured')->willReturn(true); + $healthy->method('resolveFetch')->willReturn(['2024-01-01' => 7]); + + $aggregator = new ContributionAggregator([$failing, $healthy], $this->logger); + + $result = $aggregator->aggregate(); + + $this->assertSame(['2024-01-01' => 7], $result); + } + + #[Test] + public function it_logs_a_warning_when_a_provider_start_fetch_throws(): void { $logger = $this->createMock(LoggerInterface::class); $logger->expects($this->once())->method('warning'); $provider = $this->createStub(ProviderInterface::class); $provider->method('isConfigured')->willReturn(true); - $provider->method('fetch')->willThrowException(new \RuntimeException('fail')); + $provider->method('startFetch')->willThrowException(new \RuntimeException('fail')); + + (new ContributionAggregator([$provider], $logger))->aggregate(); + } + + #[Test] + public function it_logs_a_warning_when_a_provider_resolve_fetch_throws(): void + { + $logger = $this->createMock(LoggerInterface::class); + $logger->expects($this->once())->method('warning'); + + $provider = $this->createStub(ProviderInterface::class); + $provider->method('isConfigured')->willReturn(true); + $provider->method('resolveFetch')->willThrowException(new \RuntimeException('fail')); (new ContributionAggregator([$provider], $logger))->aggregate(); }