/
TraceableHttpClientTest.php
123 lines (100 loc) · 3.93 KB
/
TraceableHttpClientTest.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
<?php
declare(strict_types=1);
namespace Sentry\SentryBundle\Tests\Tracing\HttpClient;
use PHPUnit\Framework\Constraint\Callback;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\NullLogger;
use Sentry\SentryBundle\Tracing\HttpClient\AbstractTraceableResponse;
use Sentry\SentryBundle\Tracing\HttpClient\TraceableHttpClient;
use Sentry\State\HubInterface;
use Sentry\Tracing\Transaction;
use Sentry\Tracing\TransactionContext;
use Symfony\Contracts\HttpClient\HttpClientInterface;
use Symfony\Contracts\HttpClient\ResponseInterface;
use Symfony\Contracts\Service\ResetInterface;
final class TraceableHttpClientTest extends TestCase
{
/**
* @var MockObject&HubInterface
*/
private $hub;
/**
* @var MockObject&HttpClientInterface&LoggerAwareInterface&ResetInterface
*/
private $client;
/**
* @var TraceableHttpClient
*/
private $httpClient;
public static function setUpBeforeClass(): void
{
if (!self::isHttpClientPackageInstalled()) {
self::markTestSkipped('This test requires the "symfony/http-client" Composer package to be installed.');
}
}
protected function setUp(): void
{
$this->hub = $this->createMock(HubInterface::class);
$this->client = $this->createMock(TestableHttpClientInterface::class);
$this->httpClient = new TraceableHttpClient($this->client, $this->hub);
}
public function testRequest(): void
{
$transaction = new Transaction(new TransactionContext());
$transaction->initSpanRecorder();
$this->hub->expects($this->once())
->method('getSpan')
->willReturn($transaction);
$response = $this->createMock(ResponseInterface::class);
$this->client->expects($this->once())
->method('request')
->with('POST', 'http://www.example.org/test-page', new Callback(function ($value) use ($transaction) {
$this->assertArrayHasKey('headers', $value);
return ['sentry-trace' => $transaction->toTraceparent()] === $value['headers'];
}))
->willReturn($response);
$response = $this->httpClient->request('POST', 'http://www.example.org/test-page', []);
$this->assertInstanceOf(AbstractTraceableResponse::class, $response);
$this->assertNotNull($transaction->getSpanRecorder());
$spans = $transaction->getSpanRecorder()->getSpans();
$this->assertCount(2, $spans);
$this->assertNull($spans[1]->getEndTimestamp());
$this->assertSame('http.request', $spans[1]->getOp());
$this->assertSame([
'http.method' => 'POST',
'http.url' => 'http://www.example.org/test-page',
], $spans[1]->getTags());
$response->getContent(false);
$spans = $transaction->getSpanRecorder()->getSpans();
$this->assertCount(2, $spans);
$this->assertNotNull($spans[1]->getEndTimestamp());
$this->assertSame('http.request', $spans[1]->getOp());
$this->assertSame([
'http.method' => 'POST',
'http.url' => 'http://www.example.org/test-page',
], $spans[1]->getTags());
}
public function testSetLoggerShouldBeForwardedToDecoratedInstance(): void
{
$logger = new NullLogger();
$this->client->expects($this->once())
->method('setLogger')
->with($logger);
$this->httpClient->setLogger($logger);
}
public function testResetCallShouldBeForwardedToDecoratedInstance(): void
{
$this->client->expects($this->once())
->method('reset');
$this->httpClient->reset();
}
private static function isHttpClientPackageInstalled(): bool
{
return interface_exists(HttpClientInterface::class);
}
}
interface TestableHttpClientInterface extends HttpClientInterface, LoggerAwareInterface, ResetInterface
{
}