Passed
Push — master ( 3c17ee...f685ec )
by Anatoly
02:54 queued 14s
created

RetryableClientTest::testInvalidMaxAttempts()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 3
dl 0
loc 5
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Sunrise\Http\Client\Curl\Tests\Decorator;
6
7
use InvalidArgumentException;
8
use PHPUnit\Framework\MockObject\MockObject;
9
use PHPUnit\Framework\TestCase;
10
use Psr\Http\Client\ClientInterface;
11
use Psr\Http\Client\NetworkExceptionInterface;
12
use Psr\Http\Message\RequestInterface;
13
use Psr\Http\Message\ResponseInterface;
14
use Sunrise\Http\Client\Curl\Decorator\RetryableClient;
15
16
final class RetryableClientTest extends TestCase
17
{
18
    private ClientInterface&MockObject $baseClient;
19
    private RequestInterface&MockObject $testRequest;
20
    private ResponseInterface&MockObject $testResponse;
21
    private NetworkExceptionInterface&MockObject $networkException;
22
    private int $sendAttempt;
23
24
    protected function setUp(): void
25
    {
26
        $this->baseClient = $this->createMock(ClientInterface::class);
27
        $this->testRequest = $this->createMock(RequestInterface::class);
28
        $this->testResponse = $this->createMock(ResponseInterface::class);
29
        $this->networkException = $this->createMock(NetworkExceptionInterface::class);
30
        $this->sendAttempt = 0;
31
    }
32
33
    public function testInvalidMaxAttempts(): void
34
    {
35
        $this->expectException(InvalidArgumentException::class);
36
        $this->expectExceptionMessage('maxAttempts must be >= 1');
37
        new RetryableClient($this->baseClient, maxAttempts: 0, baseDelay: 0);
38
    }
39
40
    public function testInvalidBaseDelay(): void
41
    {
42
        $this->expectException(InvalidArgumentException::class);
43
        $this->expectExceptionMessage('baseDelay must be >= 0');
44
        new RetryableClient($this->baseClient, maxAttempts: 1, baseDelay: -1);
45
    }
46
47
    public function testSendRequestSucceedsOnFirstAttempt(): void
48
    {
49
        $client = new RetryableClient($this->baseClient, maxAttempts: 1, baseDelay: 0);
50
        $this->baseClient->expects(self::exactly(1))->method('sendRequest')->with($this->testRequest)->willReturn($this->testResponse);
51
        self::assertSame($this->testResponse, $client->sendRequest($this->testRequest));
52
    }
53
54
    public function testSendRequestSucceedsOnSecondAttempt(): void
55
    {
56
        $client = new RetryableClient($this->baseClient, maxAttempts: 2, baseDelay: 0);
57
        $this->baseClient->expects(self::exactly(2))->method('sendRequest')->with($this->testRequest)->willReturnCallback(fn() => ++$this->sendAttempt < 2 ? throw $this->networkException : $this->testResponse);
58
        self::assertSame($this->testResponse, $client->sendRequest($this->testRequest));
59
    }
60
61
    public function testSendRequestSucceedsOnThirdAttempt(): void
62
    {
63
        $client = new RetryableClient($this->baseClient, maxAttempts: 3, baseDelay: 0);
64
        $this->baseClient->expects(self::exactly(3))->method('sendRequest')->with($this->testRequest)->willReturnCallback(fn() => ++$this->sendAttempt < 3 ? throw $this->networkException : $this->testResponse);
65
        self::assertSame($this->testResponse, $client->sendRequest($this->testRequest));
66
    }
67
68
    public function testSendRequestFailsAfterFirstAttempt(): void
69
    {
70
        $client = new RetryableClient($this->baseClient, maxAttempts: 1, baseDelay: 0);
71
        $this->baseClient->expects(self::exactly(1))->method('sendRequest')->with($this->testRequest)->willThrowException($this->networkException);
72
        $this->expectException($this->networkException::class);
73
        $client->sendRequest($this->testRequest);
74
    }
75
76
    public function testSendRequestFailsAfterTwoAttempts(): void
77
    {
78
        $client = new RetryableClient($this->baseClient, maxAttempts: 2, baseDelay: 0);
79
        $this->baseClient->expects(self::exactly(2))->method('sendRequest')->with($this->testRequest)->willThrowException($this->networkException);
80
        $this->expectException($this->networkException::class);
81
        $client->sendRequest($this->testRequest);
82
    }
83
84
    public function testSendRequestFailsAfterThreeAttempts(): void
85
    {
86
        $client = new RetryableClient($this->baseClient, maxAttempts: 3, baseDelay: 0);
87
        $this->baseClient->expects(self::exactly(3))->method('sendRequest')->with($this->testRequest)->willThrowException($this->networkException);
88
        $this->expectException($this->networkException::class);
89
        $client->sendRequest($this->testRequest);
90
    }
91
}
92